From 0b9bf27a0970278baa5a2b09e6997673a75d444b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 3 Jun 2015 10:10:44 +0200 Subject: [PATCH 01/20] =?UTF-8?q?Stack=20handling=20improved=20-=20no=20mo?= =?UTF-8?q?re=20StackEmptyException=20And/Or=20handling=20improved=20Prepr?= =?UTF-8?q?ocessor=20instructions=20introduced=20-=20=C2=A7=C2=A7pop,?= =?UTF-8?q?=C2=A7=C2=A7push...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/jsyntaxpane-0.9.5.jar | Bin 558178 -> 563622 bytes .../lexers/actionscript3_script.flex | 228 +- .../ffdec_lib/lexers/actionscript_script.flex | 212 +- .../src/com/jpexs/decompiler/flash/SWF.java | 2 +- .../decompiler/flash/abc/AVM2LocalData.java | 7 +- .../decompiler/flash/abc/avm2/AVM2Code.java | 15 +- .../flash/abc/avm2/graph/AVM2Graph.java | 167 +- .../avm2/instructions/arithmetic/NotIns.java | 98 +- .../avm2/instructions/jumps/IfFalseIns.java | 113 +- .../avm2/instructions/jumps/IfTrueIns.java | 112 +- .../localregs/SetLocalTypeIns.java | 268 +- .../avm2/instructions/other/SetSlotIns.java | 4 +- .../abc/avm2/instructions/stack/PopIns.java | 10 +- .../avm2/instructions/stack/PushFalseIns.java | 109 +- .../avm2/instructions/stack/PushTrueIns.java | 109 +- .../flash/abc/avm2/model/HasNextAVM2Item.java | 4 +- .../abc/avm2/model/IntegerValueAVM2Item.java | 11 +- .../abc/avm2/model/NewActivationAVM2Item.java | 5 +- .../abc/avm2/model/NumberValueAVM2Item.java | 17 +- .../flash/abc/avm2/model/SetSlotAVM2Item.java | 4 +- .../flash/abc/avm2/model/StringAVM2Item.java | 8 +- .../abc/avm2/model/operations/EqAVM2Item.java | 5 +- .../abc/avm2/model/operations/GeAVM2Item.java | 5 +- .../abc/avm2/model/operations/GtAVM2Item.java | 5 +- .../abc/avm2/model/operations/LeAVM2Item.java | 5 +- .../abc/avm2/model/operations/LtAVM2Item.java | 5 +- .../avm2/model/operations/NeqAVM2Item.java | 5 +- .../model/operations/StrictEqAVM2Item.java | 5 +- .../model/operations/StrictNeqAVM2Item.java | 5 +- .../parser/script/AVM2SourceGenerator.java | 15 +- .../avm2/parser/script/ActionScriptLexer.java | 4472 ++++++++-------- .../abc/avm2/parser/script/SymbolGroup.java | 12 +- .../abc/avm2/parser/script/SymbolType.java | 485 +- .../jpexs/decompiler/flash/action/Action.java | 2669 +++++----- .../decompiler/flash/action/ActionGraph.java | 974 ++-- .../flash/action/ActionListReader.java | 2022 +++---- .../deobfuscation/ActionDeobfuscator.java | 4 +- .../ActionDeobfuscatorSimple.java | 4 +- .../FixItemCounterTranslateStack.java | 13 +- .../action/model/DirectValueActionItem.java | 8 +- .../action/model/EnumerateActionItem.java | 8 +- .../action/model/operations/EqActionItem.java | 5 +- .../action/model/operations/GeActionItem.java | 5 +- .../action/model/operations/GtActionItem.java | 5 +- .../action/model/operations/Inverted.java | 6 +- .../action/model/operations/LeActionItem.java | 2 +- .../action/model/operations/LtActionItem.java | 5 +- .../model/operations/NeqActionItem.java | 2 +- .../model/operations/StrictEqActionItem.java | 2 +- .../model/operations/StrictNeqActionItem.java | 2 +- .../model/operations/StringEqActionItem.java | 2 +- .../model/operations/StringGeActionItem.java | 2 +- .../model/operations/StringGtActionItem.java | 2 +- .../model/operations/StringLeActionItem.java | 2 +- .../model/operations/StringLtActionItem.java | 2 +- .../model/operations/StringNeActionItem.java | 2 +- .../parser/script/ActionScriptLexer.java | 4671 ++++++++--------- .../parser/script/ActionSourceGenerator.java | 1600 +++--- .../action/parser/script/SymbolGroup.java | 12 +- .../action/parser/script/SymbolType.java | 445 +- .../flash/action/swf4/ActionNot.java | 5 +- .../flash/action/swf4/ActionPop.java | 9 +- .../flash/action/swf4/ActionPush.java | 31 +- .../flash/action/swf5/ActionEnumerate.java | 7 +- .../action/swf5/ActionPushDuplicate.java | 6 +- .../flash/action/swf6/ActionEnumerate2.java | 84 +- .../src/com/jpexs/decompiler/graph/Graph.java | 383 +- .../decompiler/graph/GraphSourceItem.java | 104 +- .../decompiler/graph/GraphTargetItem.java | 617 +-- .../jpexs/decompiler/graph/SimpleValue.java | 10 + .../decompiler/graph/SourceGenerator.java | 9 +- .../decompiler/graph/TranslateStack.java | 40 + .../decompiler/graph/model/DuplicateItem.java | 29 +- .../decompiler/graph/model/ExitItem.java | 9 +- .../decompiler/graph/model/FalseItem.java | 68 + .../jpexs/decompiler/graph/model/IfItem.java | 11 +- .../decompiler/graph/model/LogicalOpItem.java | 6 +- .../jpexs/decompiler/graph/model/NotItem.java | 14 +- .../jpexs/decompiler/graph/model/PopItem.java | 57 + .../decompiler/graph/model/PushItem.java | 67 + .../decompiler/graph/model/TrueItem.java | 31 +- .../decompiler/graph/model/UnaryOpItem.java | 2 - .../decompiler/flash/ActionScript2Test.java | 1613 +++--- .../jsyntaxpane/lexers/actionscript.flex | 194 +- 84 files changed, 11171 insertions(+), 11238 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PopItem.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PushItem.java diff --git a/lib/jsyntaxpane-0.9.5.jar b/lib/jsyntaxpane-0.9.5.jar index bc4a42add2bfde2d7117126a4c17c7fa10de8b88..1625e6b2e7989947d66a0f04c8f287b42349442e 100644 GIT binary patch delta 381526 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

+faG@y@Ot{cAu#@z&o>+|f+Hy2{Ph_PxvPt?X2< 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%0D*}r+lZHcvir|7H2M4|so;{L;9l@o} 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 sPUy#OP1k%w4JWC2p*PgVV@ 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 T$I9z>bdIZk3(j>+cPlCD1uh>r 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

2eCItP-b%t#5q@q!R_(43*xyWrxw3re?q}&b z@q<$B@z2d5@!M2y-s&AFitw94e|<`KsUctr`23MDL(YRi1ztLW9+lfjl$kyCyW33f zcP)Nj5>-A1wl6hoU!lGTu*MG_v>vxTvd)V^k$0ghfN1+ex&KNgW!xuUgh08wZucLD zJ$ZL!{%s||tvS^b2GxDDzguDW0GK<*_1N5BXnqHy=1pDyp7t9K?~{JQ7tV>?bChjm|qdbzKpn$423q1V_Lvos)cDd5P$s*yV&R2C1cpZ*@K)d z8Rk(TtKdWe?l#gJM_NFQL6p6Gcx!1LieowaKv_3@%?VAye*!JAHQ z%M}O#==Y)^nMgONDJFq&bs~n^$`S?#zbAs=ZUq;>J_R#&!-+3Igv+{P6uCLdT5F;` z$grSp!HgZtCn9Xt)3X-aWwjs4+e{WVz=F*yRa!VsZEp=oCx`lE|*XLHI%`RB7kyZ?Zsqtag?qS909^u)R zDWx1J@%I3_(Ury)H_wjEkBxSDMGq1PQFj#r`?J*pt(@N@!YK(q7c9+2!QlFm9SE}l zq4NoA6bvUozHmnA8BkH|eAozQD%!t{R7XVHxO%8iSKE|x8(RU#aII7Yvo2}1bs;~h zV99!-`kB%mfuDGa1b-MJlGa0KJWlzEP}(I*$QLX{uBYz9tG=m9Uly{9a!P8cZ5CHB zxys~Zk0SjDG8tUjb$1T=t@a(YqDaCA@TA2tL(R02kaTF4S`ubaQwKHDmQi*3J2QQK z{qqaU2$X=bpG?8&S4vN=SiaB@Uf{$rawbzTF*EtUE7x z9@OM3NU+nDnGid~0BMj0DUxlza>OqS?B5*H;Dp(o3Wa6zJSH8B_95IoR3=%tfNAgn zqy#;&C-YBBrGQ|uN}{{&UP&RX*&8w&!ZPc8L>$O++)ZI+pDf*Y$l&jS(w8-MIy#EV z9hLL>-5N#Y;9-5~n8e|%yU8(mMwpi3C<8-~vXQ6-smn5+^MT@#X68pnM)7JH~n$#D^mcT9RH02C1^5mbO^REQ2yi!Q|7Z4XjKX4lV`3UJfra;hs zJUe{J84}Pes$1iV4TS%l7!!*TSMsw?l%0cDR(3@OpXko0Ns294V&+M`m(>QD!{lij_hy-%0>qVK9XI-IP1hx8 zm0%pRa@?SM#Nm5-C%E_|G+3P-9}Jd%W4Tm4ENnFe;+ zgFM|$enBTG`&DrO3e%@7=O4O=79X^#XZ-FR8zQBb+twCit;S|DCkFQr;qPdRATnT< zbHF@F$_Yi%gC7B=1#sTiLJPaS3>Wu~yX-UrJxGzF9a#o5736Blw6@Z;(hFraNbte> zr8qp|12vGSOCHpHOkeU)DLAg}m92$ehgk4tA(rMH0tm-btadkDsCc-s>0wDl z@)QNMX&2qMm;Q=<`xtw8YCF{+90#t@@yQWtQjJpxO*py+Hg5vB?7u~Ir-Of@s^xoX zQxXbwu%7exh;Gx;%bX0}clsSUJtfiv9D|Z)|7MsMIOnz0lC#ypW$_DAHWa4oErD>+ zfb(mJVxSP402E{zzY2hFN4M4|>$AL|dmpD<1-SPj>Y76VFBpiEP47yu1l8gnV^?%C zYC@mUf!Vdtg>|YHg(%E|c|lwhWo1rH%(CObr%PKp-MpG+j?_dAM_y6}Q*r{3z7&1~ zu{$z6Ze+8N`jKpn>h~bP>tmn-I8>rxHm6B-iX<((0c46A+In$=gf&~ne`5MTICf%j z;gH-xM7O==eUa^Igx!~*Dq=Cj(q@h6qbi%cKXxM#Z(}2yZ;}q-a0CdCukcb$l~tq?jAh2TOhc5@Zc5}cZXzgcXxLWPH=a3 zcev!oeZTj9_m4fNPIXOBPtWW#)%Da=3u24(X^za0$#okg7{Qulhv~~!5zH(%r9S9% zjm%~y>7$m4@OdpC4K%>~5`Y|bh8&KB9MBCIXe+&WS-t>cxaXilZodSPR5D7VD77$Pl^2!qo(?J%~HP!zWJT!R1~JH z^g`wt!_XsdP%8%!`?74)SPYe1i^Iz#v#)<%Pa;+85@+LTx-pVxUSR=Mhka*>)~@_y zJy~pS$Nt74tmDlUNY@wwqhep>R{_?R815%n1Ls0JU$&0s4KB$ljloIRcnzb#2cDwX zrS7@m$2CEvl@l^;J#080RDmmwZXHm8KYEKuwaex;Wto4V#$JRrtxIz%$DP}gXg6vh z@yj$`I_`;?`z{>Exg@ov9-k6YuPEAM==szkhn>#Wr-i=)m|D3r&}injuon2eS~srn zdKbQ;$B$lI=X8qFWPz<54!vIYbI;NFXCyg#E%sm_WG+l=7%Cc^m|kl%n|%Y7GF>zMZVmcfoVHl&&>Uv$aQA56cCSvD zO>ewb5=Z4mFF-d2!kTD~cRln<+Ev6?6nwuNSoGtjfZ!EvI&7H06{;V<2^iTVq#5+) zCZCMl&6_6&aAQ}*(7D-@wQ)|$DE61;XB%qL&RE{}MvtivKJV})Z#LQ?&G=fx&tR1D z7Q49*1J!zfr9b4}461=3ix<7Lfo*olVkl&WE152j&y{_a-ODsM^SCcg zAw2(u78u946ioNmiZN?5R^v#x2y$8D?yIXa+VJx53jKXGo04c{iXUMcGrKW8A4}tJ zYg*Rc2hE+dBz+#J)`wlE*g3;dSt$qK_VTSJXCiok)EtzxljHN1*}Gp66ur0)tNtaL zleh$DtnH)Q!K^{!!8kWPBM^qsOs8G}a&wVW7eE@GTh@m&*CC?JG|^h8n1f@|&h-3U zYM4UmqBk%bqU;&}?J%O>yWh3k!d#Fhc1g7aLXLQV)O)6^+!J4Mg&)a(PbkPvAx4el z=z%_6^IOVCGD%05n=9`Ol9q^SB<^&qfN@sv1U#f|A8ze%o1fMXbwHNq&``8S8V^scx`n`}$E`!7^cKxjnG9?L`}fFAJJOR&&q70&(5Hf3tx) zgFBc^tQHJzc2~o*Vj>&aJ7WnMJ^>vYjT>RNXc~NCM((8i?vm7p<~tA=2@MKU$33*N z-*P6xv^%%FqKbdOa%~+IICGfe*P__g%PZ5Zu;WN7__Z ziG-@c5%p5I|3Js(l_|Us6g_)^^l$ZnW#|<8k(RUm_P-0Xe>ohe1di^faVnr+j>d2Pe>diRUx zODxX*SZ%+LnWsZxqk`N$=nd!~Q<6wA;*4S=Kd>^!V7h(_$vFl(lUt)9Zo#IQ{K5~) z55E!8sxl-fZuFtsdBSh3*rY)4mkRG`Q&Qr`Ei{*eK*jU5Tt%$C8t&%7^5|jF>K&v0 z*2j;

W0SJQx2Qn0)PP_*yEFTI~3Zogwui#%vdBTow{()H-n26${8U>Ku#335~!R zr^Abz#(siciA;fEAA9Ri>=nSXSb`2Q{Ub@itavAyICgSmP&g|mR8jEAbtYpGkM!Xgy1ojW|y5`Wn>()RCJU?%! z(oHlvq5rd%hx#wyr=isZum+CwuS`Sp`$tV3@6QP>1SmrhfDP(22jBsNu%d~A%L?zo zLu4qS&=e!rIH+VSjlTYZ+$aA;wCtdZl85W0tWR_&dq)0tvU(8k@ zYdqDZRG^zugns({Xx<)p6JdYQ#I@K)Vy&N8>;9$iEP)3-S-|Fg<-Boxru`7xkKuMm z4imcg?<@bOqf;eqk;{GP@)N z*=q|Q`$@1H9NM74=pmRO+9cnMG#<>d&MTbFlD!%)1S$>ttSD6g&CUi0Ve@lf1cVYl z$i%R)q!A+k>m4CEY!QlCrjcsmM(L8eLB9`e8Bl}pqwzqhZ8XO8I|0w1&9;(8s%N}% z=rJ_gkg_c*+brBu(@v4?W&Qt!gn!8uecu5x;D|Wyw;AQRQg8D;!D|JC0tApZ2w4N( zz#-ln8ieftY7qZP$qoSe58a>>0R2O^>I%63&@FfXd_VnXr|SjC|Ih(|fKYIxf8EdC za~4^=KSj2mKxZcaERekp3_?SPFTn5P5HWwi_QxUgL4ffO=_LeU`5{?`12jKQ*B=E? z{E%?s0D2#-?g;>c58W~dp#C9or2uL^T94BJRv(g9CZPDE6*?Cn`k|B02e^Ld28#Zt zXWX*)v;8;dFSkxyJ@0eU4h}M01dugkR{|D4jsw;J%049Kdcft!49>{}mK42P=YqbZ zyw9L=6QCU&_20EKE5Sl0yf;L@|L8%JUGE7gIHoX&4GOJ*^p8%?+5wXvosiMob^zYz z2^wUu_}Ww)Uap7Q^WTS+_1~C5-WD+M4QVrg$`3oGc>u(Rq_zmy z`WOfQGGO3C2Ur7ien@{d039Dv_%^`qLwec$AG?7A0P=@!;RpcpA#I<$KN$aAm;E`w z>q9!b1dM%1oi~8zPybCFy=&qX|9i^eulJG`UqH$b(4RrkSJ3dlGIg8iO)iwzs9vDG z^Ig_2E+_ayUF}fhPu)xn!?L3LE+sPb=m^_fy-mHESZSvnuKfxkso1B*v*5HBS0h_h z1GjP#*0SjOiRI^R6F=PD*dV!e*5Kz-B~r!`phA1}pbp|meNJYjxTVC{g-}gBq>Q^F zY2?B}V z?DMI!Hu0njC*vpXbdt4tdv&g`)r{*l2G-+Nd>)T_q-Sw&^I4ei6S0CqLI72YP|-$4DE0yU5!Rn!8%eCUU`71n=RLck zN`C~x@()1HVT!|q+`KgewQm@mg9$*b3H29znV5^|j4;P5b;#C&L3A)CM} z#M$Q@7`JVY-vLVeqtU6GKBp3F%Ev)O(rgzjpJs}3vv9p zRvYPW0(x4O>OuU`+{tfNnI9Mn*zt^D`xQprml^sTH8+nho-CrW+RdL*)3BwUx+w3AK|Q5W?{aHE2UwN*?C2{q#FD86mF^|4iUP%g}>E^V_h0aSJXo3@Mbn)h_uz@~)%P4g$yrs3hQp%U7B7)>%XbOUKGncsYI>}*p|xqvDK zfk;@(1diy%2qmVw>Hrw>_uk%bTt6OMqQ>g1ElQ)bpS8Wu1u4^?tPK=sY}AVr)7D~r zc!Y6vx*B~$8WsDsB)(Tl^l<3@I8%uY(?BI$tOp^eg ze%Y`&4iF?3kzQ(|Ojn za)TNo4?Nv{@Z7+4CKUMi3@b~@5R-2il?bB#UmmgQXe;Sh1p6}D&=Uy zS21U)1t+9%JiRTNzx|eKgyL6eN>ePua|DY1MDdar|4Fj1Eu%gHS4TzJxj{7K&+#g* zChfNIwoyf{;Ba&jC#5H9e`joJnoPnKe8OAZzk9gqUM+#X_uX<-?dP|+1fj%ADbnvv zUmqUn44m~9aLry+CiWO|-0Z~b(ZvPTg10!VwD-gCd-e+1 z-!fw4taQMRhwMQ5i0xnA;}t#|EVv_GOM`MAZF%T}XYat-BTSa1=Bn4yxzq>}dBuM8 z62qOKE82i5Y3d567Rt(!thTG{VFBfeCxgWr>+Bvw*jj78NE3kXzR>^r0{>o90~oK!iEda`R0n`FhzCPEk@(VL;WoG0d} z0_8^*=kvy~<5~40*0fyl`YF@<<-=*EG}#x=le=acJ*bhnz^#G!*mzX3|OZg|i34GBqjL;^eS4QGD;Pwq)7nthV zB0k-DFQ*Fp1&EFwKsLu`%&J|C5 zAo(}_XcSx+mc{QY&W9m-ZWf+|SZYE-3aMbV;fke{Z|6;n)wuc;+=QW4VYwZUZS zu&+`mv>}~ZlPH;h4}IAWuS*S5Q*v_wzFef?h#hf|7e6Eol|m?vVP!ofF0F{2y#)k{ z5^p0Fm>d;=wY*6`K4q=D)!`Vb^nYfrfYTM@aI5U2lOsHb$>{nbtCx8IPjTiV=gX*R zXer%k-Xg$|#v~J_tsG7imeW8wD`H^7uJ|h4Gn;NAu^5PoeEw--Q(Q`Or>>dl9CG|O zFFhLf+R!1wNY0;y$@mUpqzzC46tcidrsdKvv)?a5z`8DkiwOH5Z(~X~F*7yKBLgck z7v2cC!{-t+Pkyp$u|}oD$YkAee~-{cz1ilg;i37Mx@sifrcdzA-0g*TgH;*2nf(Of zdOzXG=yraJ%$z=1X^B6DuEWCg(Y+My=MtXUIX1$4Ih|KCHB7iWRSpz7Mo7)uYg7wA zy>8ur0>YlHCOq44o*?~(=bRmw6 ze29LbK+={BEdLo!MKm{>f9m19#c;;Fe6iiO1*}tKAdGuB2Y0pjiv3exlenosWaFr> z{YXvI%AdX${#VIN_xG&3YS%>KqD0r^Mbrk&aMW^H*!OfDB=O`IvwVu58$g5e!uaKC z7R+6|?iPJT%`MijGW!;Vw1xZI#TM6m$20E@2D|Z^*xc9rf?$leX!^*zez@7&W_1IB zzrf3FjfeKR-l&Ta!dc&>lwt_J{O`Prs0>GH@}<_2@BiVeH!>_MbMq-XR`BI>$g?j3 z+*=y?LPyaQ6>BASkwf0V&<9HnUi5r{)0qQS>U;Q46{;t@RrIYV(Njnd$4wWI0 znwuzPs_c2RCmQoruj|9zw_RP>?kFHn;Q_w{rud7(6Ji$LUG!Ip1%ES{KUEYZhv(fd z6L4*B9oehowku^|v$pVs9^E2!(KTKby;btYGFW2le5g+YIdiDhY^4KKWktZuzz@XmA(zo&3Xq!uMa>x z>w`uDB|<=R0`cpysXq}&m;`QpLHONmUfX7}(N3vhg?pbh%yPG=B4Qle3g;A5 zu5r(J>J&1tz>YQAKN!%TjrHLCR%`qN7Hv~1W;U!w7m>lhpzrZFBkVYcfi5=c_2adJmfB=#xr* zz1Q>?s4fE|D(!%VRzSB5;JqUwCuU_l;y>5e>%Q^5gL%hi(tEqe5{=A98eR`!*m8yHj5bOezW zgU1TL=~e3%R=;+Su=5*fOVokD!ohDx*d|n3f$%$Ns74w1fs54$pBM}6(wLad;H*zG zJEAD8hI9RbsKMQ-pToR;p(6*#tHu0`@t`zVh_bN!NbJR822f1FQ4c=ldsbZ>;5AVg zFvF~pQ-o7Uqr{}W*hOF4z=WEp20=~oi+j?YTZL@6F|i9j0WLA+S=Z3K{n|P4Vbbwt zK!2d1NrA}PBIMWAqzU}!M_xKnu3=UGmH=lQW7P>epXXNt78&_T!~ge}lz??i+D+zR zh-)CsAB0}oo<{w2Z_Ww$nBiKiNd0X!c!3>D7%G{>?zArVA3jJrpm=j)dS{Y{^Pjlu zG#&_5^UwE)dwC}@H8J)Z@r4{FRwHXvo727)TNME=TlVn8ruRk?2BQSSTtUudrqOvM zjRD5j1_h&Rcip<+OR(=HW+Oo7FCvJ^5IW=o3(<+rutW zbHBnxb=UmDdbTTRlhfBUY6cuVSz4=84`1?v91{1JePv>==|CA4!A%x626u&|T2jD3 z*_Z+b&{fg5Pj(0TJVM5rG>kQQa{W&6CC1=9%c7dG{T(HY(t7v$KQGDrbsmlqORQi{ zy_>8M0S-4oE`*v}T_<%{7LinAThqxa=?A}Z?>&{6XlXRnWrWxrtBZ*Pi%J9O(#2fv z#Wj8t_7w4zO61!X<1Mf%a85=IUe^NYhLN@k8Q48u_3w?G>Q}v|FxP_u?V*QGaA(;b znDmvub|A0G{(89}@*FUtNp-A?7~=f95DaNZ+IZG4qR`8lNY#iJhh+|9(?cy;?;)*2LSl*Fe##Pg7;Xy!rnFF!*g|^sjgPMgPEGl!SNuEqeh#H)O&> zgP{J4T1i9CUj8!?{V?IRgF$?c4Jg|!aiMr4$GmlB{haricQh_t0c>|w?eyAM7gSf5 ziu(He9_PZ>Qk5>2R=e&vi;AU2^q1m~6V#5`3AGGN0;&%5bq7 zjX1x$4)daMNE{duBcJh4O!)HXXn?7V5i(2dih1v{h6Q8Y;&e^9VVxq7jfAw8k;!z@ zNy1LFx5-S6ar$ENLRms1tT5LjJu${4+&(h_LCmYae@G(|k7Pl_OOBV&jdDh&3d)54 zw%5x?p5b8)Ggd9&@d=%kTrJdRP$bfsiy7|;#UC?Sddy;x5~ODRIi&!3*AX1P9aDpL z*@BjgMuGcpge+EG0HOtOuhz**Lrh6>b@Ww-i8qR#cJy!+qn<4EHgc63TwVk2e8T3q z8XxmB{I^0_c+4>Z)Doz@_tHZfoJtz! z^g>NVf|*u!NwQBwr5o{DJb?Ztu#WV_XoS+imG+8uq1TDIS7-lkXdl8J)5)gDtqGs+ zl{L$^Lv9FRkb?*=?=JH^^5=Q`&pt6(XR)!%bT%5{S+dJu+B8_S!v>@bTa)p+;TC1af|j}jjgJ*WS<-E?U7>*k*z}3;rFK*CIKfg zxnv$yJc4k849?jru5{+5SB*O0_6jwPu0f2bBtR9}<<}KaU?^8chr2(A(c>6mt!C)p z1$?-Hqa1l=xNqMkYA%oAf@w5w2LUmr+>!!yJdbhiSdd$Yn%2h2Mu09(&U7n{6O+4} zJ{CR8pADucgTBxP7kA2|@4MYgWmdC);rj zExt^LD{3+r@W^;>!8! ztUIXvNjGUXAon6m)#4Ck`^tRf#Y!FbF;yQxPkk3YgOD3KhVv^G)`-*az2CJ<;`K3_ z18XHXVRHMJ3ZUDrEDeuGr>v%uat4PhNcG-!nRZ=XfG6g9VoOzO8VaQ}Iu-6G)`_oF z{*KTiS`0Ra{in?Wh3ECH;C5(k-bHZSW35U&u*_=#FW=}!5gCZ-N|EcJT6_iUsW6yT z5EIq4ds3YKis;13+%aLdHrW>Lzq{BhZD|7(TyHN*XQf=dQ9f+E_}V|w*l7T=agId&M6A;ZGtoevM{xSROyJYQV( zl-BY&q|6B6m$Rk6UF#YGM}n-Dw2a3mNjS*;WqTce4Ij*xWHtO{2Avf(GA9k8GSlzs zYR98(x*^;6b3D&DOFM16k*@nQ1IcXWJ)Nk7{;WbvM^`h!DMh7cb)K>*vLiSE80V6A_i1VcK>XS$Y-|H3! zTy`vo>35zx&hru$zTc%ZfX&hM^TptqSr6}XznEw~>v^w)A2;lcxLP3oay(5|wj}p2 z0OH^@sD-;56*Z3@#|Lnwt9D?^y@;SYbo27?o|j8(q5jT6d!`Fsb0@Yfcr{om`-IVm z>!u~r!h`44cq@}#AiiDeE$G)wX;H!r|2(-(cGRQS!Bj@pry#qo=IFpKI6ixaA7$I% z^ROCtXWq7J;bZE-LEw(aH&#ih_3!eUa;?#CZS7G{S_4Zl1eZso~+@n21 zoGn=Cn)v^YIw%Y04d=fjIOqexqbxo^9v&2h3C#%SGw*Tg?j}ieHU{d$gth<*$R(08 zEs2vN($y1w5|Iz1@FMjmQIms=*iQuJbyor`o3U7QkGxFYa1%03`V!Xvq%?$~_JPx9 zz}rw9y9`3nKeF@^lEan+laa2$NIzPVi=SR;g48Aafu9z^t{!23?Z%Y); zYdGSn(`$1}uZf0Dh6Mjqu7L}zu+gz?@?-Gb?j~`L-6)-Ni^JI%jyX{08UsDfq~l8d zo(;|Mw-N?h{L2aJX5LpDTRO*P$tB zb?6D{<|VGvzHOJwP}t{j2+nH}SODEn-bQDhM)Bg0B4T}7wc;B;j`IP!P*#n>psM+%}MK~d6bO6%k)ljeuYMX!cRs8Z%h8|kp{!L zodzU9F!24w;@nDBpeDZ?1A_F^U6{km*=cvi43yXI}ZWR%eUsn}(3*=Jkyg zS-nOw^ZP?7SoDZ4U*f>^kE5dbIcgM~BtwU24+Ki*B9y~Q zD9$)EA$(r7WCzn;Kxm_PYptK~*j9QGE8ll`Jck!XA^wV(3Qn;JL}r+#rZ^$ayn4D& z?y61M&t)rsocSY0SFel)r%aYgkW;xUp2fZo?P^*Dj!sC_Idzn^jhiSad}%h!Y8M^{ zMJ2=LHhbiCbgpD1C5|zQ3_XQ12A&*UMgPzwq3LN7X&)-a?-R_5F|Jch9ewE5Ned zI#)pb0sAK1^NR_ReLf5Bw6-by4T1gg?BV8K;AGEjCzkJba5E=6H?@;G(KU63l2Ve( zXKj?PWp?D2^=rU9@mhRZSjXQRfkPQ}>%Vs@R6aX?v3pq50CL~%+-G(_IY5prJ1&0} zwbON{WJjA`O?+0dykcYkebXSu*Y<|@Oif&OKREQ|iG=u)qCgPHpNUD^;+nL6^KF>n zoS0)EJjH#(AS_-uycm?YEs*0f@HlELpwdec8S>jd1^GE%*b5yX`gkkl?ph)p^~>$e8ZoF0H`+r~>Z=lJMXekKQEjxtZHKxY< z5sqSlsQYe(K!SMCtPtM)(I5vr=#KwLvA@|(&86?qf{6|imV@U1?FoYjDt!UKfMW2W zYk=jjL*CG6>Df?yF6FCqv7b%c{Oe7ikYWaLn5M@9{apC`{tz;k_8^Pd48rRWxABRj zbk{mxPYW5W(TwFf_ZWWHFI-;a>!Z`6M6o;@YgGkFCMBFB~G>C>+kwK z>h=d*T6|XJl^Jm~Z7sgg@DW2a_U5W`mOu(@FaO__5@;F#3I0(HeZMNkNyW))NYJr-16KZ0cRru?55tVuIlE)wBgtzB1P(mJKLoVC zWF3Kl94hlcN4r#6k7A@YVbDT*N8t zIM(_#T6BSfZFFLus~W%RzU zv#-WWOx>dgG1lb_r%TkP0Ef8i9@@k48JNv@+6?%R{eY2u;kR0y*e64pL5RM70~JDKU1v#~4H*|+;qU0)zKBL5ogV^EKV7zwmhBxLSzMuJo*i(Mvy~3#)c2 zIPJ66Og*Z+J3Q5=xjtY%|IJJtcN^c$lRrFj;h6~@1$5CUV`73hGu#t-gGS+PvR#V8 zuOzO|(EKVq9m#H-*Yz*+kLg1r8cno2bY}AU@o4MzNISxKFGkH2Ki7fT+se!i((0is z11PC4%{Pa4!pCrbo%bUjxj|iN+yv0B=yo2CM%rczHSl@@{Js_npc9}L1!8cawy*FQG1+%47ZmUn_?g-|Yw)t6% zQ*)1Kc^95nb!ZEA6-jn$crs^A-zA*!ao@>K!#qet^t_TKIRW;+zT7is(CXetv@(Ju@FFF)APW)hub0I-4#4iC|fupJ_}}1|M9tWat|G`sH43prEy<}HqG_u z0`u?0x36tAaN&e}@3c=_QfmIu6HLw=y+OO{?u&8-50OX`QFOmv&lqAk70MWiZtIKy zlkWi1;*w4CpHPpLrFNlFEMA<1FXMMpQf5kLcKgb?eS(QTYAbb?4uz5~vZa?q^kb`J&vlLnjKpson(QvoZha}n zh^p62@$+YfShUtJc0ZKH6fcBXNXlUzTlm$DQWaq8(IYVTlanTY4>FqZ^h zc?VUAp+EMzw=Vfg;zyL=6!46pby9aT-VN}>QO;BmM;hsIr5He!K**xm(H*Ok+3`U; zLDc}W3CEa2D4=R$RM3c(IJ_)ZvZw zHK~vBxHbNPcJgM{cRtVz3b|X*><*kLv&{e~1M{BM)z_j#e1M{o)X>o%a&%Jb1MG`2 zj3cy0qxTWML=e?GE=-9$n{;KFu;8Hh^cC$Y#E{a!SqsLi4^^1nw^1piv`{3mqnI%O zU^U+Rsp}5rfOD1%rkClhA?qhZgJ_!%ogYqmwtC1qWv_j)ANhn{=U*`uhK$hGFB!=| zM97?eC-A7T%{1gDS7V7>q}3_ZPDvYBI7swIOJVKi1-5&Ya|i{Q03_{sOV6KY7Bw0Y z2GA5;H~zXc8{cbsLvK3^b+X5XJ>=iF_r$tl5V6WqkuWvF<-{)_#(MYh+8~n6n%@C> zLCN;MiDdm)>a$ghGR9x*?riu3y{UJEmaU0px50l$XtZ~PMvJq~_0jHzN#VHcP@1GC}AUR9vhu_X<4ns89n5pR)b>T=cnkB{s>vl zFZ%aNDH`@d-~?D)jO0;VY3WkCf$fRun)s&Z7aTi{Ol)t@i+2zsuj{h{5!1Ds+cE0t z6&RL)7XGN~up8jJJ2G%V5^B!HhF00KBIjWk58OM4E)phycQ5boSGXGD4W4~lY2Tj; zM`uA=B~EbT_j>CUz;6t|pKBl!#VS_lSndpnpqzcyUdyK)>Qu?4EDTa#tKVXIj~eVR zy6>#Kn0B*TD1HI_U1>MalMmc{m#6%jjg`4xXawY)eT1M^UqjGN9QaXIHOgFNaKG3d zJss6ZQR%2N?~g$XANa3-7ES$J!;`aLh&h6NV z9X1N-oAn(>aWDn66&{CE7TMaDg;N9o+7k-I^`h-X$Eb(5jEQbQ5$u%B>8n6?&sK*g zf9-)1TNTTH7%h;9A#Ue*gnm+~T2?kcvqC3pV-Mk$@4%kHi+QbfsdvHoE3c}$A)zeM z+1gpgr$@j^?(e?(6y*W@8w4dZ;dZjE(f4xF#wX|CnX{vM-1?&l+?zA1)f{#L&uA5M z7uTd(iau`km0VzEtuAfb*-mBgTn&O%R#>c2!CeiTOO*L(CEm!gD(5_pyvpR5fpi_6 zae;$sf9XGJzRJbr?~55@r$~T3^kF*gBHPP*&G+xGt6of|x5Eu1u1rDQJlvy&w&ZPd zF(jo4x!$Et&f3N55{vdX@HVg&yIjKUgSGRSGVI?m_I*M zDy_2G5N?RDq9_+f$yW{^IHqedb5{R44%8ggB6~i~hLLqOW4TSIuE2xT+!xE$@(igwLtyrZ7MrOK)K9w&DC5p(_i?LlMeUj|4{QN zkZ}K1xB7?CB$tJ{Wgxv5fG~*V$Hxj8rXh|Ry8I&yI`@e5)9oF?;XWYzJmACAMF8b6 zLbE|gtrCLf8KI4Ve|VDM^FC3Aa*{__+(RPIrb-ym({WG(M!A0E3SIn6appqD@nkSe zmIe3R@=PArP^t%S#l1-UMV;u&5op?XkS;Ae8{yMe9_f_0XGNfa7f!#Fm_$uUocCkO zqC24n-^EI~-kq7u2NsIjTkh%Stqf*{@QV7V^F6EFmC;~>Ov}&6a20j^;!ur z((QMn$TW_kQZ9KiqFn^2tAO=utVJ#U{(;a>JBq=BmQ^bfjPL~F$Py#z96IIMIS(kB01EyG)V$1z*WtlTOk37hrd) z8L^>WOP(NhfeWIxwJnfeI;|z7m@tUuu($beOnB2OQT_(@(`9Q(i4%YyWrxMqkyK3t zlr>Rtc+c_?*-3YjT}Z9hh}^MZkdnB(b|C8DKT7mA63+K!9O62>(q`EYc7yM)__$7| z4nb3m4-QPBgXi>I<6$*R-F=E5k|meB#qJ#-?2KMz1==f8tP`P|3^cUBcyoHW8&r`+ z^I_E}%4yZ8(p5slg3grjuwRLd>!cCh#FWgP*ZA-By-rQBNoZ&sLcf_xBa(ld2wk=XDuJA6 zNMOMHVv?UoPO(6}#OHVR-jF3|^C8Z9TbU4oKR@oE#%pVLiIn#zdyF-5`eWW_KVTle zmwn~-^xt1v!>e`{EKtj6V+N}@Lpoylzx-ypfD&ZWOd6OaR~5-nXCZ^&>pF(K*0YsJ zhm`C4vya=LykfiIZ^1r{c04P@y3?{7G?lJ}?}!P?=n0{7&QNN5x+G`J5ujOujZX%h z&bMm0$N^Kj9>Axg>}qxUH^u~t&#j!HPrF^)WDrkN-5DLwmOE)5a=u3KX%LlE3D&+> zqDH#yO*Cj#6)>>1nmPSj<=jYR`V$1dy6S{+{g%n2xymTxOAC5J`nHyc!I|@;A8^tp zD!gCLI@&$?&84HB!&p^+;n1VD`H*3|MBsXvy%Or=*pNB2q0B}^ebq0NxpIEGKyS4% z{0ZKU!+Y=Xq)jH+WVXJNkEJNQo&G@*cv3VyhJ+W5l!b|>^C`VVhjGsqex-_;L|=uK znWBzd@7suWBh$ZBCOSWkmp@MLsZ1Sv$Ee&*8`^G$UvN&nkEO-^LCepLk2wH56oifTy&5$eq*&$FgC_3*MdsyG_}2RP)# z`TQ0vXL^x#3PZm+yy}Rh9gafFjBV1B zWvptOX6u=LNRHEQ_FHOV(55E92|;3!9yrzgGB3OO#*xQ&@}91xay}CrD>;1WLA<^r z!w?~ua>S8&Wo?Pm9GzyW=3wOHeA$gB*#7Z-$IR1A021B)`MOg)`bo1Zxm~QC6MwmH z`JQR)2r0_T|EDVVKfq*56vqvHM?|D|KUd-%M&-p-g+UsO&>W!XNEjs04|eDx;C_N! z9+yuX4J&yB&O02cJrA#m*qVgy1&}P}MmP)E3tRN7v)nXN^cwQ>CP!1JXi9aS>430;y>f&ezE zsulr}9cuj+uqY!K5F9EyM11$k?ofk@C`$m-qYA?>-HjulpvEvW*yKS^Owg?JJ46%f zZ=MnH=el&yNZ=f^Cb~26p`9_n0b8>|aPZK#28@aY^IDV?cWs~rM$uIar^#|iGW4yO z$k*K^hImxr6G|loJq8F58N|d1?S$EoM4{cj0C&%MzLOr9%x|qZD7gL&)W8WX`)L&f z!3Es{KK%;nf7=uJ1~31ufCekP;V zGp2S-FeQY8G=H!ziFHoaONJDGdvarrqfIj@(C~#TqYK~e*^^q0orz)men>6Aec?9Y z<<@i4Ws)&0t=GO}>Nkhxi72SK*tE3c;!m~3Y8)uZGrcjys zQ;f*?tseg#h!f)jD5^cEP4}oo*KjkWz4ooZMGJ~=*6wGdVC*pver~R@mc+su`%RJQ ziXj{3g{w4pJ-nxoZ~ju65EvaPqtQ7DZC*0ys#9a>D3qjapdSZx7lm~J zu2jp2iWkKO^@H=#6b=AN1Z<8Ft!v2o5lgfeDYX6IUkRRB!tRxL7?tJjEqCTj)UZRt zTC4$t-+<<3b)eOak2 z=a!~ScX;V=Y7P&hNz?~7w=e6(%58w`DJOPwWq#S8SfPDfKMZ2dA}uC_kB^3d&5UJe95OVLU+Gp>%`0sJN&`P>kjwAj;Dly z)X&2uCb9-%jOt<5fUWxIEN-E8yf z2jj%HiK;D5uviEA`#VAcFW~TL`X`+qsjTq4U&#zw%ul7C5Wwx8MOh70G)*`uz??%; zumS~T;8%=HcLyJz>12(IH% z!V&i`#%1JjbOUw_7;?6V_PCoH%Ml>pi$?eK0A@+VUCxQJ=AsCc<7BYJmL3ipP+7%< z$qv`+Kg%sJ@wo@h3~oz*BVP)nQa_fJHEq0*DtllX%avsy*)Z5=G4%#J!39EUsRLs$Sx{6 zi2B|1Z`MzN^oT4%%-(^d`?i;j4KuEh0?z)JGOT*|uk`V}#I`5k7WlG@Gp_-IbRiC{ zeCC#1>3WAe$Je!$aFkZq0X)0c-hbzg_=1P4W30{e7lG==QNa`W136W?=uKUtkbe*M z`{%yg~fmJR|i%@L2G>Ljd-%L?YPz zf0Ic-@5v;Pu%b_f5JuxQb1opPFVG}Fd0uM~@Okf3_b6BXO9hqcKG>Npse#lRa;9{T z8~hQwnl17-;&MZfhK(%@p?Bg+M+QfQgBq-<3sy_2xUT4 z{#~~x0-KXWs6`{{mo>AL-qF4eqflDB#@{Y>OI1JyUgQB3;N;?o(lB3(WU*=p4SAdg zNIN*pa`*R_o8A1KfoeS+Pm)$ z%jYJP=h*rUSY4%9qfCwdGu%o6EFuFpsXRp1&! zot9@opHYQiQhK2E1SYU1cDKP2&;==>4Wnv1s~Bduu$4;dJs``)k!_KHN(45rjZQ4T zsi0QI=&uR+Ex1zRV7ipe!;D7rL0Vgc`?Sy7|9GIk*w`tB;Oei~)@*@95H&^K}kFP!LTJ_b%g=1rlR zmU$foNaJ2n=&H4I{+gs>GCdg~TOChO4oh#{5X*CwJ%QUd`4gyF+Q|V=)Wwd2^M{?~ z1@LF-XQ{Mibtgw0Wcmr0V%kCiq|9WN27S>}uI)$d%`)h>S!6N2wtnOs zcA2i%Paj-Qr25RX*LiH~xz7}}GmMFl%N!}iM>BN|t$bGl@v_Vo=_*XAlzQTg20%5uw*=#>hKz}AMOu}6Kn@#8Pk`e}aTMW_G9mrUbBBg(QT56{ zV4lx_gwhG4JpW@7OacOm*aoNM>boLxVIdGbNx}bZV&c&dx=q zo+18!+WYc&tb(_1`+e-Y>`Qjpvs0F`D|?n~C2O`KOUZ2si74WrY*`Y85K6MOSwm7P zp_L+Or_?j&oV%Mlzvq4bc%J{>_x^m&C(V4X?_4u;%{AA|IdcwfQ@bK~#!o+KXIu5s zUZ(j<((}Pquaq^;4?RPh>x&NlY=cRa7wV% zELaz`IqnXAVZ;%WaSNYY^>fH9jzXf@ENW`6WEf@H9lz@j%}&RWKjY5WpP`*wT= zH+zrVX)g0`+_g9EzUJi8pqDpO;nd}`Kf+on1ZlPQv)ycz_NzUr;KHi@B+OgGg#VYt zu=w)1FkG8RE1yLB?zxzQy&otS%kD3@{@xzFHCO<@BWwe0;5XrU4I}mM9_QN91+FXI zo)6s4R6EUlm~N-Tbj?d zPn=I2v{em<76lZ}ROHyyl~7on-kF%YPuK2OekF&C1FdzWqDJAO#F&Y2$wmRsOD(x} z_J%1<0($uT6HD*tkCt*b3eFUBclY>FH}*?ZnfSPOs(g;QT-D_CAS~;bJmpQjr6-x* z&MG{&1>(G39U+%Llv=mNn!8|hpZgoVGrMM(WDSKw9i|(U9DPE&V0h?r_RfD@%=8=5+V|64yUzT>Y4*s}vvosh1);b&^r~E53GgY0K@F zgK$m=t9*C%S+~AlV#y#B_PBdYF7K+vujRsvfl{we*oCD&dlcgzQ1Q7abgQYtTjUsY=JTc>E_nCN1CR!ewt`j5METU1(}`&ThT5NOsAcRmxp0N%>3VZsUA)@#>9c z)$zN!H9t)_UG5Qi_5M?e9fQfcUYXioCn%l7Rb_Z`^PaY6ZM)~)KJ@kccdbUT?wY+3 zZgZZ{cQWnItyk-{C^ub}Wn4Bi2)N`cuyQ;mmfmTMs+RTSGraIOSF`inS6N59PAWZN z;b1xO@lNSIMz@*g^x?jVM?W2#3Qc=_aGx;LAwN04_t~8xW-$-x`2Jr4?Np;jnOrqq zKguf(r8i9V3Hoxp)bq==L&uPH0r~mQuj;z210=VmJAPzJCHp-iSgN{cdQ3|HNO1G_ z>7p*!nE%#{Uk2qbJhicbT*}@dN>R2tT=LlI?oq0g!Q4`p^B+Ekr(SultnkYztx4D; zI??-?R&TqnclE<@o?IpKvk%A$3O0ls5r-P%y(r4`*bd)+oRM+*mn)e@-F}%WfppP5 z@~qp8xl%sLZw#>t^>DkRS6QtmI_awW&f|o*Xh6rqdF6Yol{d-ppJEoQFKv^_VPNaN zI^liM)6le-lgD=#|5%b$D&)UO=dv<`z!BLqx%5moljuEZ3T@c3eP%9oc&c}O(O^7> z@2h_Bdc$U}RL$S2yT|^BJzu^uVD!bH^}0dBXKmX$J$Z)o&R{*!7oz5TANOC%D>=E% zBQf>cqt`+Zqi`t81t`7bk$25-iWGxWBhJ{mGix4R$8bh+!m z)s**=Yxhr{e3?8{{xi6}rK*wLNbDBt*AN%pLttHCdcaKh`H|f+zORh+MZ1CzQ@wen z6c{*l`Rfgli>z}$XqU~;?%#hYz@={4PV?rNqh$+SwS$Xnu9If?*fd_OWa07z#hH7q zbdeFeH*5Z8?(caKQ^R2-u;OneP?K4}Q?5EzTPV6YVR>^!bjYZ{>ssrVW`^EL`otP75Ub-|wG9m8K=jGfa>o16YoI%}7)NA;BF#ZYD$!=Vhb zm=_6r!`}+|--Tz3+qTf)qfQ)b%gy6_6S$c9UiFOlqmkWa#uk#3T4JZVx1Qnb(Rypk z_VnYQk006Tkpqv%gSXXvZ@3nyK~+cH`2JR7QiS?of@Yo;^XAZ)2x+6t7k!3mWx|>@ zXPyVj)K_gtzIf@RjJ$N8JCx(KBRrb9`t)K!mC@L-9?M3WJdMk}^}p~MGJTDOf0$hw z2e}>uYf(JQWcjA2meTEbXKO=-$=E{oBO9;ww%hKu42g#ZldaW^v=l^)``p6ERwG^IfC498MR!7B&Q$I4o=cC-_PA&9UL0Kt z+wWg|)PAJ)+uiL+61^XD(zo~&xc7i%fnBP>z2$tx?sJm^M#?woTNt*T9)FX)(foYXJU#_)tDVL)3L!tK5w@t2C`-GS&za|=cxNJASn`|XHszfl`?BWs2goj= z4Pyd-DOeQXkwt+e-iYP5p!A|EIkjQ)T`RwDl|fpXUY#=LQwMHTCK@1Fcob5gqw?BU+sH&eNyrS848 z!7zC_Ca@`#k-O9_IPCDj!(i$l~2*`_yOAGr&*`_q^{OpOq;xaTy4p7#Al27)+0acd@0p;XO*Q721+thp9=BI zIrx0$e$qCJXa$dlJ<0g=>aGV519&WQ!!_n!`aBd+3F*tiAE)c{)(1Nh)l)Rr((QA_ z^|PiEPkd0#*S^t|a`Z{^O3Tbwy3*qU++X)ad$iJt;@EKYOa-a$Q>tRkMR&ZvkUlSM zn)@Uov(6$ROcxVZbe1LeaY=qLS+jA8=@N)cjr9i!@uHr%#s}0=dLwc z?|wLDKXZ1u>pd5<#pQfbV{ye^tJ!f!3%ix{i zLiy~>jfFCw%QrO@|1jCi-uvyV#@E}uZE@F+?J@EC-VM?XDaU<&QAunow$gzA;Eem0p zr9#a2RZMV>G z>gXtMeG9iHS&vD_Gx_4y4B>h&$bZ*qZ&4bSb=@AZ(O%wk;o%{kQVyTf`1aeksL39k zb-r^!@}~l4z89l#gs#YgQ+;G-Pi`=Y>7m`Lf1>j|8Eu=xo4Y<@)%3-bJWk5~$l1eS^SOQ~+j9PGm19Z@{jNPz1D{h|;%0GTLQRDp_C0Lu;yetG zp9=*SJdJL(+Q{?!1x|3Dk#8kVa%UT!{z(bJm86&}mN*(OHN(XYZ<=f{=A7oMX z%w9{yOYfYTO!3i;sN3~$B)cMKVsglXCelnJA&QdqKvBO;c1_~R?For>GP~YR^6%;u z-Dn;gnwWRk@vU>^qu7^CW0LLisvG!?3k#udp(vX zP?$A!aOb_EY~_hAWyh0Wufn!gI9>b^^DLvU*_VUwzCSyrb@REtyDo0`&|u75QfI}L zK;ORIib|SXXO~B-wT~`^d8J9Zhc#SF^gDfSpBl4=&4v}5Cq*-tVgx?--EM58D&NNb_Kl0kql_O)Hkve)%w>M;`ZM9FFjMwE5IKF02glD- z(Z#^Xp{o0LzBj+g+FEedlKyBEKCemaD{K&8V=`95f5R`Qt^)4j2ahtI-t%)q*S0xs zOJp%{11ttS^XtzGbdLBRIzHbwEV8R-34bNW%=^Mb@NId7 zuNC2X-L1-#N<#i`UDQe+8|CAJ(F5oWY;g|*<(@~6C1&}j4P;yU8w{E#7++YPk5)=P zXcu=s^hfINuY0^KQiD!jVN<8frmK2Wx%72s?Qt2e?S6&KB3CIm5AT1Ft5Dmp)#8DS zTUo9RIsL%vl@~IfgQ>RJo9C9ezsIZWAG}~y@wVaG^ZL-NhZJ3Y-h&se%a}3R$y8pS z49jC5xX$e9nWwFlH>x+GSa0&?)bg6|`~Y9vtZ9RLg}!107PiA#q3;F>wZl1MNkjIy zM@SM}wF@_Z{&Cm=_Z$W7cEmAZpa3Ua7M<(lFQf}dR;)s(dwru*?UK9hF~t)kOHyJ_p~u&pR|Zy29I;BdW7=qKb))RO*vThOgI^jLY08JV%e95Czc7)szoO^qlWp)I zu55xLhjO{Z=BdH_%Eh=yyzTi2wRg-Ci@qAX{aP&eb4>3h9lpN5(X;o2w`oP4$F;-H zj-BD)sjF0MWJ+Id;mH0J=uGFesPT9p;Zyme0-SwP!Nt0X{GMN92UM<&GB_l9zxq1f z9U4BI&~S)rUu|Is>y0Pj)xVFI4Qjlcq09?N(yTdRTCcT~BX+^q^wXyw_+#_Dw{5t0 z-7wrFH0CsVX4uZec2h*hffQwpC)c9(=`q)hHeBETE=N&(owMP_o73Ix>d{v=_g6ZH{QBejr*YQ1|FYgx#Yg$&i!zaZ35*&q z#HlY*DvmH^XNHc3yVEO6bG$A*j%TLtr0ikjN*8!WZ~w5BdSRuo+@RBd`zOt-5!-rW zL2`L-T%??XjkHuxZwIfz#WZnt^0cOR{AE6&o8JA%+7Wn5$yqY3-C0>L#&;=H?#X58 zZ2Q>-#TpC8vA6C&6Q*x}wU6FBlkwv0qQ}7%fqcUcU7{l%1Gzu?dIdYa8PDLbPuUS4 zrMOuvy)zgXhbLU@jf>waI>b=YE0wFPhSrF zY=yx>z~lEB52igH7c~j5Xw0hLcNmylQcI=H7tb4sfBjDSSQ^Lo&huSErW)_2ZAN<| z0;SK~e(9l3KSiHWKrK~Wa8W6}qQ2z-{|*t=>i0GcZ!kNFYd9nb>|}`1Es$STA!St4 z=UlXKmgSX>Lq1#G3!=~7x6F9+8OGn03}~j_)us56=5n;7&#;vQyT}g8ptzT8uR|I` zKi|6{=wV8E@X_dzuC&I@Wga2FB?tHUL_~7M%+4PTrx&f?{VVVo(}iz-8}7jQ{J-0# zQw#R&{2KrAkMYk7PlGC+(NP7_Eu1f^%7oP($BMeyoYIm?dQxI@FzLyMQeoJ@dK#bd zqmD!8)H9Fi$DIXMhZ=T&e7@i$!6AF>O0b^%7V#smSf}+5l0KSlXCjCILK_ly;1HCRG{sRSUV@>`vBgc1 zmr;@0=U9`OhBDW6D;W+h5z(PnWSeL8X0EoLIZPgE*GTnzx0Oxl26C?Vf0`c#T{*|R zaI%G~;cEEauQ`;t*}1(g6;`}5!x|}SbRC{DW+Rmaulb|vB^JzA5;v(`e@Kb`#qK?I{gIp1Hth&xWsS+r5Z=#_`n%^CSYlO~K1N!oPPZ zTy48H@$C2)I{f~U35TC8v@b&qnf?_1@ZHv5nIHP=&%O3ZyUlNGghQ+&xsEz;>NLht zrbn9Szw_YUpKR8{9`@*jH{xXI8IVnPes7*|VMOC7%Xv_TjTkt>61xvows}A6v9Er@1H8i%&Of zRV}HPS$TgakG6aH<9iPcEiK&?g`|W7(Fe42wEr*-2uDn(KYX08wwRGUvFB+JPsu+= zm*_QP#rFa8utUtl8V2W6S>ShjaeJx0FchAG8T@d3_^akSIYK%78NUSSg`^Zx9l!K> zQY`)WVDk5zi7Vr~oSUMI$@~5Lm*U@A?YA#&;@`m*>rhpdz1@%T_3}7XLcXcRr?!pP zDopOy@1N?J7wr-}+|##vRM4mk*2t7uM#t z_qlShkJ6XpH&G^4NwORiKSPs1vF-CzSu*{bW5J{Gv zaXwM;Ds!|Zvn=Z9;>U9?VN-i;sWdAk!x9|WjR(xTy!3e_h0e%VIKHUJ@_OG8>=Yi8 z>7`(K|6UO8Ql7*V8zbJ)XAJm^JBNVJC}-mgsgL-44}V;64{#cjz-hRcR%gd{zAn

!8)rg446+-9i;A9>6|kH^PvE-|y*p3GSqS4OkhoasYu$Uso%k#-+Vc152j zH^^^(Jo5^F+9>wKIE8bc>IMpbuSgHZ5{L%$_n({uEg8d*zQcH zw|w#T{j0}IQ>t9&gO#e#+2zQJ{`WUpZS&ugX6Gw)Z!R&l8U}TX)<2lPbIX0#o8uos zj>Y`rGDHQEO1ywgIDu8A0~uWIjXLBGe!faWugh z)J~in74NqmX8SR*8j0{L6)-PcZed3~NIGTi!`!~a{t`92(gSRPY_UFe56i5z`)Kh^ zoyATwx&)Z>KA!dQEGjJ1U><2SlKnkhJm>+TEF;bp!c zV4}M-Y5ueQ&xq?id*i+JE9yZkLMI}5I}pSoVJu8EEi5NLO*lhdi;9nd2kA#Vh`$eS zTIogEV18p;vw?RNBbTC%e)@RM^~=;gd#dq^l3x-W_>AYxHy-K))^d--R`$TdzWUe0 z&9d5C@72TjWaEHl@-gBRV}ndF^dDkh0&}T5^!eVo4~Vrq1=ey7nPS40!4$K<8IMgd zp`xFVDdroPV)*XBN$3=Fd5`|UIdqCSyJm_xu{y=vAxtsni%%I?&mvO{8*z%+(TYwn z@*Mq%$P}Z4O)=qMijmHa&qt@2JIECC1Dj&X(siAh2~$it8JJ>X&?zR!AD@j)FU z2e$SEZexGzRQ)j?x~o)Ld@L^KCCN9w|D~QHdj9itn-6oq^_-l`Tdl|*@P=-Et2yfY zuu{%Ai)t#d%3s{td7IN@zK7N36w{lwVlc;ScC~lqz%ANQxqB}l6Q(I!_fhLgKmPd@ zKaSb!Mo6&XUXJ(;KmFyXXTdioRdnB;mAzB>7H{T2!(eYI{K`ytvospMtd{LF<)t3eQ#^EzwwHcQ8f+!KcLBWW3LHvd%(QklQ1AnWI5NycpsVRGC z)-mdRglr*pVF1jJJfCcsVP(w z!-p;H4bAxiI%J$}rj(_UM$WTDpBR}dEuONd9AO{!y6r1`v9muj0Vm-CVvXSir$MUz zT(yPR`&-2EQDv;fAlMi?*pnFR%p>TyO=>4!IeY9h*G>>@wA#tx8-miLj6CzcS(=lZ z2&w+L#&tkt*VXEkBSzV@eaoNr*Xqu=xmT#KJXdVv`C41k-tB$*>BnOMVP}=VT%uY0 zROsKSgt~;6?;vm+2Upz&dR*nP~{FWkwmC}f=7as3M>~2TG&6I4Bxv_$es)5_Lf_esMwtc-h%^pk28q($ZomP zS;E0v+NiYs?YUV)d)cAKPK5Zwi+L+YV~tPi)z8*^o-cN!Y<(Q5c;oop(#4RmxE~L~ z9RIXe2}wS+wHTH~!Vd>5{CLfjIM&rk2A{XNdD6T@R*tR*V|fZFj~XI0XP}Ff3L4h*~LzQ5SQ}|O!2;f5o`E`L>6s28MR1cp~~at5|cc?F=Co^{7IAN3x!Rscbl{gNCQuD%jV@k z++*wwou*p={B$CfcnfFxk+oXEH>M%FQv~oX9MrS9yOIGV}^K- zalG2|;(ctTVHb`MN{{qa<(^l2X;vI$z(%8YkW8rch1-uONuAH}Mb50XW?_R#ZNI&A z_!)k_l(;2iys{i+)4o&PDb4Es8F>coszN=JY%5*{x-av`jF^2cvDF;fEWscc)tZ7U z(ww`s%{1^(;vU5}ODD^H56YXma%QU3K8?8FV~Bgw*Wc&1rR05EzG9{BM)}RX8q39D zYIpeI0x>6kym_Y2NilrX;V_GEK93$1^5CJ5t%tl-y;SzPJerbll(D8cS#b79(l;{m zxznu`LA18wmv>RnT)@9b3lC5BnTDSSHJtU&8C+~;)jId&f-ASXjMw4PLX8Rq| zzwwRumRWC$%X-BXL-N-z%J}-VF*+KW)43eJZRN}nZ)uf(lw;pHT70(lMlD%xMlsb~ zr-LDV+wB*)ZbTf(Q6{&o7~q@QY-}p%M^%}-qxh;zh)A(r(ve+4X5}YGSUW=KF9-{q zb*-$>c6w;UQF_IqwOX9AtSEoQB~_98V!g~nn^E>+-|`RCeH7e%1l-5Xn=|fiN0SFO zHcttT&!~C6klz%l$KR~`kHuIT5#tWbOwbbmyskJt_^B7p;{V4T|8K_~0{_MxGETg4 z-oU9igXzW@*7wEjfKN^0*kJ)z90$x7fwRUe2JD&ruSKeFu}GC?HByz=SRbjXFnvuc zEy&n~KV7r`%b?LprN&}hK)y<4|hV63H(@Ukxy${*?josK96*(w>IHX=Cer}X~ zF#dlMsTPw)s*(TmNY&_nAyS?BzeTDrVKYRC;eL($$a{VK8Mh4Fe~MI@|FM|n$S52o zCAzsvmN!=E4{XN;^EBW=Iu>{~8oZmMlRa`fMd>gZaaO{~teutaJP&c|U`uo+Z~Hqd zt*B$Ol4nG~mD4$wCvC}6>1+!>bI4ql8OkgM6qjoIhAk{h#w;u>aa zKQeNdukJ(+N6VKJR~n_L+>2F`rS564SK&jphdCsK3cu4!ShlJ4G8&0IcaGz)p$NU%MXK2T%#v>@@Qn>kPa<+EN4vRB6O$NQ&9*Wr%Up#+{ zT13`<|B)B+t_%5XDk-sepRt|Wq!=kuPQQ4p?KAl7yKI9?&%LViERUPsae1}wTjn~X zVl=zg#d${mgO;`Hwu-md!BLPvGaJ}KVIRvJ)xTwZF#+@Yd!U=*ynOuEQS!lyjl#}BwZ zR(!k+473Vt@s0|)+$o*L`zi+N|2m-TTR8D%A*A3o)z`lkYJpg2$91^w(Ou2ZuJ3_^ z$2wP@1no+=za@MZh?}l&%6!vhvG;=(4MRS6Z2&$Pb3{aU=b~JgY>>^WB-ldNv7p;y8SS zMT>XyRNG`j8m&p5S}?NiA}+f+6JyPI+#1G^?V5BlBW$}S5p37k|J|-R2)1jM?q7ux zQmR~DE2!d2mb{MszN*Vz=<0gwQNnMjn}W>pwKuyDgLT*OONZVoEyCI3B~Jxc*InQ{ z7sy>F%S0R%IfOh5;2Gvz)x0|i7fw#G)ZhFd8FvPI;k|zf&JBCreqS0c0`q}8y~CrJ z!FN-@o9SSjF}!da$J|_g3bz5nwP)eNC}|PS2m3^~(!;}PICE?hXs!}x+x!;Bbz$$h zzm$(VfQbkf;$kssybE^%8K9=dsL|8-K#Ub0OTkGrYn;bDprAsio0-dT(U@?0CGH^h z7v&|OA$nKrXf3W1`%9_;7mWRt--N5i{xZ3aJC6PJpbbZf-8~z>iSt864cl=-nEGiy zY0eJ9?sGUZe*~w7)$390 zwUpby1w_CHx^PA?TCZDOph}WsxQp0QXWwVmhEV{C!ysU(!`!Sqj(dg`$@=Usz1}2F z5hL|qEX-H{5_6aYI7!6P{NM%d8z#~JnxID0EROIA3#U1p4yIY|0`3h8gX2Eono(u7 zKjRv)&kkfLB{gIK-W?!5vdkK$k%cW!LlW@v0*|g z57>s7@32u+u~$^CS5|9MR&)pnXS7ySR#bWYTE<*XX0ZQ$gX&PjDCNNia1txDiBcSt z(8vm@Fe0?71^a*21Ii!pS5`=s3i&P#EYAk;$JLe^ZKgf zS)KG;a6TKvfJs*YX$l|mtm(_V@D!4Yd?5+`h@=*fXI&xZlP0I&phQk!lac*P%}zo+ z0$Z^|8!=W?o{|D)ZK39Yt+@Uc*2)gLSpyzphlJ6=3oj!HJ}@T-BqWTCW+EZ@gP-^x zMDc72SR{Z(P}a(PRiFQ}#C;%fgGLa(!2ya#pm0A2s1+?`)*dPj_!lviffJ-^BB{b~ zbS}iOP7wtXMGj#|y&#Ac?&F3Sg#Oh+f&|_L4{<`O>o}1Q17km=ax_$+^i5bpp_+Pd z0iAXrsoUUoE{G1(e*j6X!mv9If#aJ<`Rk~){xXvx)PGQT)>dkEc!2vaQT_%%dPb6m z%H5@2zn4JcMhRRE(t2wY5}`$_ z=0VG{rpeL5!_geXKk;FBRMUPmH75t$9a&{UbA;(oCU-jKf0@G29C#83ieC}X=@-$>* z!3<<%vc%3sK=q0U9}nyx42hsnQNedr{Wvl*D)6-%ITEOhI_kb^gduShDI;Mb%Lt-` z??BN_BuIT-6iF)riBbX`VFeLTN7w*K%zCwr8$K*TsON6{WS0$~C<404lTg^~MA1c- zys+?Jw6}7ay*ii??Lc*z;Ikfgj?Q*z0DCmEe7#t3A%G+E!@Gu!Lkqo zTJIgApx&RIiMj9*8HgRtsY7y>T>j?p!LHH-wNGe#s_SPaBRjScd=ihO7&7<2aCX>T z3}QoPn@CFv&n%$PVcLJYOCT75Yoo>87X!up3`HiIteS9ezFHiVhRi7M-g~Z?0`c9z zdL&6odmn~QOCI77A4(Ae{-B78LMhy$xmGLr1j$G^Ldal-g(V<%w80d!LK_=_0f+Mb zYjo*H31}wxhy=uj@}H6bG-)Yl#y~nt*0VGSo|GUo3cj!`C;}K|9m~IVax#@5!3Aqe z5-Rny_xte`&>j5wk&<7wyI!wpQfshP*P6}d22ef)w=c8_5 zXJG(Mio60Jkb*YBO8|*B8M8EKvd-$P#ag9R``M zI*8{;NnLJ#4GP)}`d^)-#!6jT)ARf}GLSS1EcBJT*8_k7KqFG%{#yhf*Q#lsmH}F& z+#zO60h>o@Jenion*mMQI-0C|M6}^1LgjXE0yIUve>1Xb?&IL6as+!wz17Hekduro z5;PF$SiIg(kl;ke2rW|4n~{qpUGStV#7TjF0kWlFUs*yaF|vr&y+RVRKFs3a-oHb4 z9LdOggQ5lHAa)2LVu;(r1wWUCxF{~nz}9kv!IdEgpjY3a&`|(ID|@Jp+f)MBpBm@` zQt#6-2auAmJkkw_IR&0LZ-exACTJE?AE-bEE2%(S@Dw#UFMLX#VBN*r?v{Q5)_oP! zpVXIcr6A(jux>{9)3>loKL=jZYn_{pX29^W3Is=JRMWRo3=Fgg_#e_~r<56kCMrOJ zX#Hp!9V}i0#yT*-B}t4Yc>@L=R{(J((rR;zws>ElKp3zy84~Cf0Sqdy2yH~6UQ8*y z#sG#)X3`|kJ;E4tgCsfUs*l$ZsWD^)cyWLyHTDHD3_qbr7`5}exg_s`Ce{G;6C{iG3urmlg#)?<7}VK}e8VcWNvMRX1JHN^Ow&>% zZ6{`e;RCG5+2NYa1QXq`tM}1+&~`z zD+Ia){Z1_V`>@7Kpx`NRNx*%Z!8*8Hg;1I0qNm`aeBiT#>y-O$hcIx#KU5%LwBDW7 zu*@XTYZ~Z9I@Hn~G3ZWJNJ0o1HD(IIr&0hb2QU{>y{^I2DiAkpsR}_by$?Ctsx=x! zTtEAtJ2ztwyr>E(qe@Jc?|d}?nDKy_v@uV5A}DTHKJYIqqRB9)_B{!(2K>tPuO}(? z!IZ95BaGiy{YneJSeKy>sWt*(CriSO*1Pu|c5+pf`7`{3U;BTHF;DcgcUYG`W zuXXsmLy!Ve>XA&0Sx}3h1UGA^-%9}X0i>cN9g>xe zK?AgaCqepdQfnxJ9GJZh@C>B-Hs@l{w!f@RU$>`y1gt04srv041`WOdswN*pXxp)G zwr#gT)sBPJ0x7jvF@|^2CMdkt;z*&AWf=5g4WLHN0+}|H3a(Zyk&}_#2lS*PaJmAX z(uTI6qY1a+fRPVSxDnKk6eW2PLCL^AI)o{i>*!sU8+;6UrRgN^q!MCf+!5P;oZUq>6z5@2@QG(>Tni zOIT7qcp3KV7(fUER*}CD@NZe1{xbw603X*S1e%kcNn8!UMvW{$u zd0kM|?^F~pGb@Dity4_AN?1*qi)65%i!3OJ38f*TJ0i!Cf2-S}IQjI71} z-$=t5M*)*xr{I9=^dM2R^={6&?==F7H#z^SRIvg93+Y3ADE2bNIe`^n;Bkz}$b?9A zkg!IvoUo!B1wH)C7z_)J14u{& z(Ud{PA}R(nZ4c;hpbGI<7RT^~fEA;lWLZ_jv}3AmD;Q~&ZU35k-&cYFJryM@))vTE zqLh|+I|TL7c#eu?+;#J_bkvFZ_KQv;iI6HX%`O7r-i5KKb9m zW?T^{C!7(mwk&ta_bt1@faN>REPV)(gYO6FDFu5w79=>YEFoz=g?qOlvpw~kP9 zuHvNzb{46F$|r^X+gjIWF#N)I&{%E;1mitrem67&^h6V=JLw=%=BC07vPhDO32R-X zJNmcVfoYI z;0tw_{tf&jYY76U+JO|>K!`x&lYld2z@Bdh{M$eZO{l<{A#kOlRssf77&2r?2Nl~i zfxOQc5iWwSWSz#y@b6ghi6vk!nL<)1R^5Q-OC?z7^MK{0Fmc=>4wyTMfPDs2Gr=Z1 z2u>-pxxHDQ9PI6bp{`6K@H-zSw*Z@fyUid;blmNpDf~nRpqbzz^)}JxFleh8B!t#v z!VC=DTLoBZdo48=9BWP}@QTVuxfM`Q7GNP=251&x_#ksg5M{|Q2P{X6vDCq z;y==IzJH(w4Clc`>OWqWAb8Aw=ve>)wNkj#0<12gEeMM~J@*_@DIiA$s!TdXwv{1J zEwqn*BeDt=NP-}&&_d0;S~%~G>b=O!gA`6mP;>!P_T&yo1ZBCh1F*cW#8ThxfW*;? zG4BMax>Z=J)(z0v#ELa6;nZ^p8Udk7UqO*8(0D?efm>nr@B1;fwwQgfgcphYS$e9*3o zpn=YH44~e>mhgnnP}YAYJl2Zg@dE@xRJZpwVCatAAPg~nTWAA19KCHc+1bFl@;dNP zz~d8tWpO`l5wIV|s2Ntnw>XE8$xEOj$jU&N2uH@R(I7#<(hkDG*KG-VRYSI*V8x-e zd2%nPaWJzTVYWHK|6_m_Sh~tOMxl{aDPFV|0d|1QdvrCK22OuNO#}Dn5XkNvs)!W_ zQGG0!DOT?WBI?DzM5P4eR&NJlTc}?+K3FpX?~e!Gi!@Z5{z454+e2dLE?R;c{YSXa z9^#@D{Yed5bJ7UFHyFVeQBK$sihgpp>q-QuhZOLHq%l3+FM_}cW*T-_bJt%1pNbQR zz$PF-8nF)kCJ02c(Qu#ws1Z4`(bruAZ7&I03e=DID~rn_hxa%@>@c30h8_;$q@lrX z${?21tbW0NCn(`DsGcxU1Zj~pN=ztl0}b=)O`IzRc^gwfg!~2qolJt~rbY15Xh)oM z0H*$o5w3C|_;m$_zysv~J^?NX60sg$8aPgYMi^#yB$$M>Bk09?J~UYkKI%wlj}p!i zS`DxqDF$@|(GBqjf;vGID+KpAg4GC8tIH>5A31}Sh(1t})JZ4F(ZC)0G%~9;!OCx( z5eDqr1OUM#O#GF_Nov!;WtKEztLD8l8}R2VXyPZJiNWMb{FTK$+d%{O?*qLazL#bL z{Md=0^c8%x?Rn6N?x4v?`(&dPDji`3tbyCNtd_^1m+2M_FqSkOl%rgj6% zzILD5a>3~T=1M3^ z=T-LGzeSPWa%jPm3em#0ZiIe1>j6ml5=iqoh*itk1F{b#!PZ`&X4-qeq6e|2fnT2# zL_uQ_ZTAv7KBUXX8;f#q-C3yGiwaBRA? zSr)Vy;{8b7W!h;Bdbk33OQ*dA3+UM%`|=M^W*JmKVo5r&kzS|SxL0KjdmYaoG>ZJzou+ZB12C2Q$K7a@+ zK@cKv@IHtGt=%KD#OjNHz6@MoFM#+fi}NhQptk@NE#fIcV0{5g9G5SnTcq>?kiR$jnO$@&tSdgV*+ z%?i*;CF`2HtOJve@g*2_>!Gu;H-U1Z8vr)> z5q1(UNIz3U_O6jBpVWSj+(oz~;Z#3Dv0^{s%MloIu8q_|81`aNok<$nb;XkVgEoK$ zFvOo};0Mh82`%T0WcA+1vI_md-XdZ%HDg8>Vn7*D>&np?L7+Nl-?8imvNR8o1S$CU zEDa8J*-xO|k7RK_Lb4>_n*D?+pc6?I9mm?T;3E*A3?R4`z5tL_3vPWNMg_9K?V11r zS2V~Xmxnw3K%?=02L7P^Z_Xeh^k)han*U0}u+9=UMdW_gp(Z2C2BDuGaqJ+o1KO_p`MO7hweR&=9=rRVaJ3)XFKl8Z`8cGJA4uUk06R>M;Ossyp z@84P;ra|%GcqDeqgZTNXbAuEC$@=saZ zEfl{Az8^+#_wrfz@Gy{73N8}_L->`&iRdHLn_%!z;3jmGA2|dD*-tDLJp0EA?>+=} z))D>uhkIQjfFMF*@s|PoTNc-6fRH$&@~g$D4zHdA~06%Nbo9#L_9BC6iaZI#P`wwJSjhg2@%hSJc!M>I=G2% zC|M`;#%zrcctD+Tb%Yb&Td_`PaK{=U@IH$*cm9Y64A%)=uv#Mo-gSTt67*<0=v%jS z_&8f4UIlF_(!v5N@hLk2wBNBl=X9~nEX<{%G~V}%kA%dRVQqstmR>B#@@ zYew(BMu<54Ne<7gY6~ps^`13&q7UferM!d0G!ND()xB>Gp41T#Pg$)K>hW14MDzw| z%WR1OEmP^gCZBZl6OZAnBdrO z1bvz~@W4C?wCDf=-2w~8f^8=-hG6|zpkM=7PQ*d_sO6)lBnEDlzh#CMW}Nk6WxOA^iw~-;I*j#sP8&EC}Kt1LS2anDL@nGVve_ACF}bO;qb7hc_*V z`WV;Ieoe%n#5oCN5l#RseqbE{3LskJStM~T4Z|abh&~q`>UOsSdCr7$9kl~&g;bDe zf++LpV}RsQ7Dj>?8k)+G2vRLzEEO>)H1z~XCBFlA#sd~ooALa?ri%lGGOR1~00`xg zRv|T)*d)OJ62$OG7SU4BLVhAyr^~S{(kWrBWso{<{);f{aYzduNd6Bllho&KtU{m! zpL-mXm5wIpz^B^5gU;^Z5Cdu%*Z~yb3}6{`mk|jaxHuJ}UUh<~vhFE>V5V+OKGENy z`Qu2wSmT;}qIIDD=fS-RFXU)S7?|Wp)wFJ2BZSxu$~SNV@WozVlSQ->l<$v(>#zHO z@8mkZ#x|l5HXu4v0o8m5F_jwiWmvGHlLmqn{#$GEh(?1J!}^qG6j3{TT`|sg*9Z~K zN#P_YE2Vc$7SX0IAz3#D)?|@d7B24&buTC?VqH<3!)t^{&8s*akeZIJ$tSfj-VBg` z{?VFzQbYT6f4cH8C{!GHD^eFU{RF;}0lA~C5ZG?%X9K)W2)N8hyie~0g3?Aq0JPsy zPk{oDJ%>w9gF`LgiF#qw&`=hV13x4z+EWN#6LvjKFlxcDcd^|7g6zzjlR(v9B2Xu^ ztd-NCEYDX+f;N1U8a#K77&TfJ$q^wEg8j2tIP>?&5N0FqGXYi6J7Sg~N`;os90D?U6LE3}?A26sZC5Yb;YP8h8 zGoaML1vD$mgO&*%paN$?h}rttAp6EgO!DuMq&4|+IUqlB5zPk=|I479XyWEi7$^(03gA{V+Mxokj|Qd&0ef6jrxG)(fxhHzUI5zvEz!Tu2%@ zFqN7Mwv3-*3H6+E2_Zd?lgK=Eic1I)|_?n21rfovaLGyJtyDn1Y5V)7&RBezKg+Y-OPbU^lBUA5a_ diff --git a/libsrc/ffdec_lib/lexers/actionscript3_script.flex b/libsrc/ffdec_lib/lexers/actionscript3_script.flex index 8e393ed1f..f0b94ba62 100644 --- a/libsrc/ffdec_lib/lexers/actionscript3_script.flex +++ b/libsrc/ffdec_lib/lexers/actionscript3_script.flex @@ -1,16 +1,16 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ @@ -21,7 +21,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Stack; -%% +%% %public %class ActionScriptLexer @@ -37,7 +37,7 @@ import java.util.Stack; public ActionScriptLexer(String sourceCode){ this(new StringReader(sourceCode)); - this.sourceCode = sourceCode; + this.sourceCode = sourceCode; } public void yypushbackstr(String s, int state) @@ -115,7 +115,7 @@ InputCharacter = [^\r\n] WhiteSpace = {LineTerminator} | [ \t\f]+ /* comments */ -Comment = {TraditionalComment} | {EndOfLineComment} +Comment = {TraditionalComment} | {EndOfLineComment} TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/" EndOfLineComment = "//" {InputCharacter}* {LineTerminator}? @@ -188,19 +188,20 @@ HexDigit = [0-9a-fA-F] OctIntegerLiteral = 0+ [1-3]? {OctDigit} {1,15} OctDigit = [0-7] - -/* floating point literals */ + +/* floating point literals */ DoubleLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}? -FLit1 = [0-9]+ \. [0-9]* -FLit2 = \. [0-9]+ -FLit3 = [0-9]+ +FLit1 = [0-9]+ \. [0-9]* +FLit2 = \. [0-9]+ +FLit3 = [0-9]+ Exponent = [eE] [+-]? [0-9]+ /* string and character literals */ StringCharacter = [^\r\n\"\\] SingleCharacter = [^\r\n\'\\] OIdentifierCharacter = [^\r\n\u00A7\\] +Preprocessor = \u00A7\u00A7 {Identifier} %state STRING, CHARLITERAL,XMLOPENTAG,XMLOPENTAGATTRIB,XMLINSTROPENTAG,XMLINSTRATTRIB,XMLCDATA,XMLCOMMENT,XML,OIDENTIFIER @@ -252,7 +253,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] "false" { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); } "null" { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); } "this" { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); } - "true" { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); } + "true" { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); } "undefined" { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); } "Infinity" { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); } "NaN" { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); } @@ -261,99 +262,102 @@ OIdentifierCharacter = [^\r\n\u00A7\\] /* operators */ - "(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); } - ")" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); } - "{" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); } - "}" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); } - "[" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); } - "]" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); } - ";" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); } - "," { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); } - "..." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); } - "." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); } - "=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); } - ">" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); } - "<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); } - "!" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); } - "~" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); } - "?" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); } - ":" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); } - "===" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); } - "==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); } - "<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); } - ">=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); } - "!==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); } - "!=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); } - "&&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); } - "||" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); } - "++" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); } - "--" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); } - "+" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); } - "-" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); } - "*" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); } - "/" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); } - "&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); } - "|" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); } - "^" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); } - "%" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); } - "<<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); } - ">>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); } - ">>>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); } - "+=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); } - "-=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); } - "*=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); } - "/=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); } - "&=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); } - "|=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); } - "^=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); } - "%=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); } - "<<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); } - ">>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); } - ">>>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); } - "as" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); } - "delete" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); } - "instanceof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); } - "is" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); } - "::" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); } - "new" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); } - "typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); } - "void" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); } - "@" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); } + "(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); } + ")" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); } + "{" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); } + "}" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); } + "[" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); } + "]" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); } + ";" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); } + "," { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); } + "..." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); } + "." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); } + "=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); } + ">" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); } + "<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); } + "!" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); } + "~" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); } + "?" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); } + ":" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); } + "===" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); } + "==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); } + "<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); } + ">=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); } + "!==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); } + "!=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); } + "&&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); } + "||" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); } + "++" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); } + "--" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); } + "+" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); } + "-" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); } + "*" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); } + "/" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); } + "&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); } + "|" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); } + "^" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); } + "%" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); } + "<<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); } + ">>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); } + ">>>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); } + "+=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); } + "-=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); } + "*=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); } + "/=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); } + "&=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); } + "|=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); } + "^=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); } + "%=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); } + "<<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); } + ">>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); } + ">>>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); } + "as" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); } + "delete" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); } + "instanceof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); } + "is" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); } + "::" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); } + "new" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); } + "typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); } + "void" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); } + "@" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); } ".(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FILTER, yytext()); } ".." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DESCENDANTS, yytext()); } - + /* string literal */ - \" { + \" { string.setLength(0); - yybegin(STRING); + yybegin(STRING); } - "\u00A7" { + {Preprocessor} { + return new ParsedSymbol(SymbolGroup.PREPROCESSOR, SymbolType.PREPROCESSOR, yytext().substring(2)); + } + "\u00A7" { string.setLength(0); - yybegin(OIDENTIFIER); + yybegin(OIDENTIFIER); } /* character literal */ - \' { + \' { string.setLength(0); - yybegin(CHARLITERAL); + yybegin(CHARLITERAL); } /* numeric literals */ {DecIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); } - + {HexIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); } - + {OctIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); } - + {DoubleLiteral} { return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); } - + /* comments */ {Comment} { /*ignore*/ } {LineTerminator} { yyline++;} /* whitespace */ - {WhiteSpace} { /*ignore*/ } + {WhiteSpace} { /*ignore*/ } {TypeNameSpec} { return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, yytext()); } {XmlOpenTagStart} { yybegin(XMLOPENTAG); @@ -361,9 +365,9 @@ OIdentifierCharacter = [^\r\n\u00A7\\] return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext()); } "<{" { return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext()); } - /* identifiers */ - {Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); } - + /* identifiers */ + {Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); } + } { @@ -402,9 +406,9 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.setLength(0); } return lex(); - } + } {LineTerminator} { string.append(yytext()); yyline++;} - {WhiteSpace} { string.append(yytext()); } + {WhiteSpace} { string.append(yytext()); } } @@ -416,8 +420,8 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } "{" { yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRVALVAR_BEGIN, yytext()); - } + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRVALVAR_BEGIN, yytext()); + } } @@ -448,7 +452,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.setLength(0); } return lex(); - } + } {LineTerminator} { string.append(yytext()); yyline++;} {WhiteSpace} { string.append(yytext()); } } @@ -461,11 +465,11 @@ OIdentifierCharacter = [^\r\n\u00A7\\] \"{XmlSQuoteStringChar}*\" { yybegin(XMLINSTROPENTAG); return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); - } + } "{" { yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRVALVAR_BEGIN, yytext()); - } + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRVALVAR_BEGIN, yytext()); + } } @@ -529,14 +533,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } return lex(); } - {XmlCloseTag} { + {XmlCloseTag} { pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHTAG, yytext())); if (string.length() > 0){ pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); string.setLength(0); } return lex(); - } + } "<{" { yybegin(YYINITIAL); @@ -547,7 +551,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } return lex(); } - " 0){ @@ -555,8 +559,8 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.setLength(0); } return lex(); - } - "{" { + } + "{" { yybegin(YYINITIAL); pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_VAR_BEGIN, yytext())); if (string.length() > 0){ @@ -564,18 +568,18 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.setLength(0); } return lex(); - } + } {LineTerminator} { string.append(yytext()); yyline++;} [^] { string.append(yytext()); } } { - "\u00A7" { - yybegin(YYINITIAL); + "\u00A7" { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); } - + {OIdentifierCharacter}+ { string.append(yytext()); } /* escape sequences */ @@ -590,7 +594,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { throw new AVM2ParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); } @@ -598,12 +602,12 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \" { - yybegin(YYINITIAL); + \" { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); } - + {StringCharacter}+ { string.append(yytext()); } /* escape sequences */ @@ -619,7 +623,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { /* ignore illegal character escape */ } @@ -627,14 +631,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \' { - yybegin(YYINITIAL); + \' { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); } - + {SingleCharacter}+ { string.append(yytext()); } - + /* escape sequences */ "\\b" { string.append('\b'); } "\\t" { string.append('\t'); } @@ -648,7 +652,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { /* ignore illegal character escape */ } diff --git a/libsrc/ffdec_lib/lexers/actionscript_script.flex b/libsrc/ffdec_lib/lexers/actionscript_script.flex index 350dca603..d00294b43 100644 --- a/libsrc/ffdec_lib/lexers/actionscript_script.flex +++ b/libsrc/ffdec_lib/lexers/actionscript_script.flex @@ -1,16 +1,16 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ @@ -20,7 +20,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Stack; -%% +%% %public %class ActionScriptLexer @@ -95,7 +95,7 @@ InputCharacter = [^\r\n] WhiteSpace = {LineTerminator} | [ \t\f]+ /* comments */ -Comment = {TraditionalComment} | {EndOfLineComment} +Comment = {TraditionalComment} | {EndOfLineComment} TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/" EndOfLineComment = "//" {InputCharacter}* {LineTerminator}? @@ -123,13 +123,13 @@ HexDigit = [0-9a-fA-F] OctIntegerLiteral = 0+ [1-3]? {OctDigit} {1,15} OctDigit = [0-7] - -/* floating point literals */ + +/* floating point literals */ DoubleLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}? -FLit1 = [0-9]+ \. [0-9]* -FLit2 = \. [0-9]+ -FLit3 = [0-9]+ +FLit1 = [0-9]+ \. [0-9]* +FLit2 = \. [0-9]+ +FLit3 = [0-9]+ Exponent = [eE] [+-]? [0-9]+ /* string and character literals */ @@ -137,6 +137,8 @@ StringCharacter = [^\r\n\"\\] SingleCharacter = [^\r\n\'\\] OIdentifierCharacter = [^\r\n\u00A7\\] +Preprocessor = \u00A7\u00A7 {Identifier} + %state STRING, CHARLITERAL, XMLSTARTTAG, XML, OIDENTIFIER %% @@ -236,108 +238,112 @@ OIdentifierCharacter = [^\r\n\u00A7\\] "unloadMovie" { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIE, yytext()); } "unloadMovieNum" { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIENUM, yytext()); } "fscommand" { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.FSCOMMAND, yytext()); } - + /* operators */ - "(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); } - ")" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); } - "{" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); } - "}" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); } - "[" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); } - "]" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); } - ";" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); } - "," { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); } - "..." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); } - "." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); } - "=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); } - ">" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); } - "<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); } - "!" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); } - "~" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); } - "?" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); } - ":" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); } - "===" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); } - "==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); } - "<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); } - ">=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); } - "!==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); } - "!=" | "<>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); } - "&&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); } - "||" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); } - "++" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); } - "--" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); } - "+" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); } - "-" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); } - "*" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); } - "/" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); } - "&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); } - "|" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); } - "^" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); } - "%" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); } - "<<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); } - ">>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); } - ">>>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); } - "+=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); } - "-=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); } - "*=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); } - "/=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); } - "&=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); } - "|=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); } - "^=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); } - "%=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); } - "<<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); } - ">>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); } - ">>>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); } - "as" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); } - "delete" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); } - "instanceof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); } - "is" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); } - "::" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); } - "new" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); } - "typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); } - "void" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); } - "@" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); } - "and" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLAND, yytext()); } - "or" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLOR, yytext()); } - + "(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); } + ")" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); } + "{" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); } + "}" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); } + "[" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); } + "]" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); } + ";" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); } + "," { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); } + "..." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); } + "." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); } + "=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); } + ">" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); } + "<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); } + "!" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); } + "~" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); } + "?" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); } + ":" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); } + "===" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); } + "==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); } + "<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); } + ">=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); } + "!==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); } + "!=" | "<>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); } + "&&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); } + "||" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); } + "++" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); } + "--" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); } + "+" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); } + "-" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); } + "*" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); } + "/" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); } + "&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); } + "|" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); } + "^" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); } + "%" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); } + "<<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); } + ">>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); } + ">>>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); } + "+=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); } + "-=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); } + "*=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); } + "/=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); } + "&=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); } + "|=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); } + "^=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); } + "%=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); } + "<<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); } + ">>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); } + ">>>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); } + "as" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); } + "delete" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); } + "instanceof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); } + "is" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); } + "::" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); } + "new" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); } + "typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); } + "void" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); } + "@" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); } + "and" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLAND, yytext()); } + "or" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLOR, yytext()); } + /* string literal */ - \" { + \" { string.setLength(0); - yybegin(STRING); + yybegin(STRING); } - "\u00A7" { + {Preprocessor} { + return new ParsedSymbol(SymbolGroup.PREPROCESSOR, SymbolType.PREPROCESSOR, yytext().substring(2)); + } + + "\u00A7" { string.setLength(0); - yybegin(OIDENTIFIER); - } + yybegin(OIDENTIFIER); + } /* character literal */ - \' { + \' { string.setLength(0); - yybegin(CHARLITERAL); + yybegin(CHARLITERAL); } /* numeric literals */ {DecIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); } - + {HexIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); } - + {OctIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); } - + {DoubleLiteral} { return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); } - + /* comments */ {Comment} { /*ignore*/ } {LineTerminator} { yyline++;} /* whitespace */ - {WhiteSpace} { /*ignore*/ } + {WhiteSpace} { /*ignore*/ } {TypeNameSpec} { String t = yytext(); return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, t.substring(2, t.length() - 1)); } {XMLBeginOneTag} {string.setLength(0); - yybegin(XML); - String s = yytext(); + yybegin(XML); + String s = yytext(); s = s.substring(1, s.length() - 1); if (s.contains(" ")){ s = s.substring(0, s.indexOf(' ')); @@ -345,8 +351,8 @@ OIdentifierCharacter = [^\r\n\u00A7\\] xmlTagName = s; string.append(yytext()); } - /* identifiers */ - {Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); } + /* identifiers */ + {Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); } } { @@ -359,7 +365,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] {XMLBeginOneTag} { string.append(yytext());} {XMLEndTag} { string.append(yytext()); String endtagname = yytext(); - endtagname = endtagname.substring(2, endtagname.length() - 1); + endtagname = endtagname.substring(2, endtagname.length() - 1); if (endtagname.equals(xmlTagName)){ yybegin(YYINITIAL); return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML, string.toString()); @@ -370,12 +376,12 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - "\u00A7" { - yybegin(YYINITIAL); + "\u00A7" { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); } - + {OIdentifierCharacter}+ { string.append(yytext()); } /* escape sequences */ @@ -390,7 +396,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { throw new ActionParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); } @@ -398,12 +404,12 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \" { - yybegin(YYINITIAL); + \" { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); } - + {StringCharacter}+ { string.append(yytext()); } /* escape sequences */ @@ -414,14 +420,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] "\\r" { string.append('\r'); } "\\\"" { string.append('\"'); } "\\'" { string.append('\''); } - "\\\\" { string.append('\\'); } + "\\\\" { string.append('\\'); } \\x{HexDigit}{2} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } \\{OctDigit}{3} { char val = (char) Integer.parseInt(yytext().substring(1), 8); string.append(val); } - + /* escape sequences */ \\. { string.append('\\'); /*illegal escape sequence*/ } @@ -429,14 +435,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \' { - yybegin(YYINITIAL); + \' { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); } - + {SingleCharacter}+ { string.append(yytext()); } - + /* escape sequences */ /* escape sequences */ "\\b" { string.append('\b'); } @@ -451,7 +457,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { string.append('\\'); /*illegal escape sequence*/ } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 4423c8a08..34bbe0711 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -1732,7 +1732,7 @@ public final class SWF implements SWFContainerItem, Timelined { private static void getVariables(List> variables, List functions, HashMap strings, HashMap usageTypes, ActionGraphSource code, int addr, String path) throws InterruptedException { ActionLocalData localData = new ActionLocalData(); - getVariables(null, localData, new TranslateStack(), new ArrayList(), code, code.adr2pos(addr), variables, functions, strings, new ArrayList(), usageTypes, path); + getVariables(null, localData, new TranslateStack(path), new ArrayList(), code, code.adr2pos(addr), variables, functions, strings, new ArrayList(), usageTypes, path); } private List> getVariables(List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes, ASMSource src, String path) throws InterruptedException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java index 212210862..c62dd113d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.graph.ScopeStack; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @@ -56,9 +57,10 @@ public class AVM2LocalData extends BaseLocalData { public ArrayList parsedExceptions; - public ArrayList finallyJumps; + public Map> finallyJumps; - public ArrayList ignoredSwitches; + public Map ignoredSwitches; + public List ignoredSwitches2; public Integer scriptIndex; @@ -88,6 +90,7 @@ public class AVM2LocalData extends BaseLocalData { parsedExceptions = localData.parsedExceptions; finallyJumps = localData.finallyJumps; ignoredSwitches = localData.ignoredSwitches; + ignoredSwitches2 = localData.ignoredSwitches2; scriptIndex = localData.scriptIndex; localRegAssignmentIps = localData.localRegAssignmentIps; ip = localData.ip; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index e9c33f7c3..82fd48c8f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -282,6 +282,7 @@ import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateException; import com.jpexs.decompiler.graph.TranslateStack; import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.model.ExitItem; import com.jpexs.decompiler.graph.model.ScriptEndItem; import com.jpexs.helpers.Helper; import java.io.ByteArrayInputStream; @@ -1243,8 +1244,8 @@ public class AVM2Code implements Cloneable { if (isKilled(((SetLocalAVM2Item) output.get(i)).regIndex, 0, code.size() - 1)) { SetLocalAVM2Item lsi = (SetLocalAVM2Item) output.get(i); if (i + 1 < output.size()) { - if (output.get(i + 1) instanceof ReturnValueAVM2Item) { - ReturnValueAVM2Item rv = (ReturnValueAVM2Item) output.get(i + 1); + if (output.get(i + 1) instanceof ExitItem) { + GraphTargetItem rv = output.get(i + 1); if (rv.value instanceof LocalRegAVM2Item) { LocalRegAVM2Item lr = (LocalRegAVM2Item) rv.value; if (lr.regIndex == lsi.regIndex) { @@ -1442,7 +1443,7 @@ public class AVM2Code implements Cloneable { } } if (!isKilled(reg, 0, end)) { - GraphTargetItem vx = stack.pop(); + GraphTargetItem vx = stack.pop().getThroughDuplicate(); int dupCnt = 1; for (int i = ip - 1; i >= start; i--) { if (code.get(i).definition instanceof DupIns) { @@ -1899,6 +1900,7 @@ public class AVM2Code implements Cloneable { ret.parsedExceptions = localData.parsedExceptions; ret.finallyJumps = localData.finallyJumps; ret.ignoredSwitches = localData.ignoredSwitches; + ret.ignoredSwitches2 = localData.ignoredSwitches2; ret.scriptIndex = localData.scriptIndex; ret.localRegAssignmentIps = localData.localRegAssignmentIps; ret.ip = localData.ip; @@ -1921,8 +1923,9 @@ public class AVM2Code implements Cloneable { localData.localRegNames = body.getLocalRegNames(abc); localData.fullyQualifiedNames = new ArrayList<>(); localData.parsedExceptions = new ArrayList<>(); - localData.finallyJumps = new ArrayList<>(); - localData.ignoredSwitches = new ArrayList<>(); + localData.finallyJumps = new HashMap<>(); + localData.ignoredSwitches = new HashMap<>(); + localData.ignoredSwitches2 = new ArrayList<>(); localData.scriptIndex = scriptIndex; localData.localRegAssignmentIps = new HashMap<>(); localData.ip = 0; @@ -2958,7 +2961,7 @@ public class AVM2Code implements Cloneable { public static int removeTraps(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, AVM2LocalData localData, AVM2GraphSource code, int addr, String path, HashMap> refs) throws InterruptedException { HashMap decisions = new HashMap<>(); - removeTraps(refs, false, false, localData, new TranslateStack(), new ArrayList(), code, code.adr2pos(addr), new HashMap(), new HashMap>(), decisions, path, 0); + removeTraps(refs, false, false, localData, new TranslateStack(path), new ArrayList(), code, code.adr2pos(addr), new HashMap(), new HashMap>(), decisions, path, 0); int cnt = 0; for (AVM2Instruction src : decisions.keySet()) { Decision dec = decisions.get(src); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 75beee2bf..c29e13c1c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.HasNextAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.InAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NextNameAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NextValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; @@ -69,6 +70,8 @@ import com.jpexs.decompiler.graph.model.ExitItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.LoopItem; import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.PushItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.WhileItem; import java.util.ArrayList; @@ -76,6 +79,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @@ -124,8 +128,9 @@ public class AVM2Graph extends Graph { localData.localRegNames = localRegNames; localData.fullyQualifiedNames = fullyQualifiedNames; localData.parsedExceptions = new ArrayList<>(); - localData.finallyJumps = new ArrayList<>(); - localData.ignoredSwitches = new ArrayList<>(); + localData.finallyJumps = new HashMap<>(); + localData.ignoredSwitches = new HashMap<>(); + localData.ignoredSwitches2 = new ArrayList<>(); localData.scriptIndex = scriptIndex; localData.localRegAssignmentIps = new HashMap<>(); localData.ip = 0; @@ -159,26 +164,6 @@ public class AVM2Graph extends Graph { } } } - - /*for(ABCException ex:body.exceptions){ - for(GraphPart p:allBlocks){ - boolean next_is_ex_start=false; - for(GraphPart n:p.nextParts){ - if(n.start==code.adr2pos(ex.start)){ - next_is_ex_start = true; - break; - } - } - if(next_is_ex_start){ - for(GraphPart q:allBlocks){ //find target part - if(q.start==code.adr2pos(ex.target)){ - p.nextParts.add(q); - break; - } - } - } - } - }*/ } @Override @@ -187,11 +172,13 @@ public class AVM2Graph extends Graph { AVM2LocalData aLocalData = (AVM2LocalData) localData; List parsedExceptions = aLocalData.parsedExceptions; - List finallyJumps = aLocalData.finallyJumps; - List ignoredSwitches = aLocalData.ignoredSwitches; + Map> finallyJumps = aLocalData.finallyJumps; + Map ignoredSwitches = aLocalData.ignoredSwitches; + List ignoredSwitches2 = aLocalData.ignoredSwitches2; int ip = part.start; int addr = this.avm2code.fixAddrAfterDebugLine(this.avm2code.pos2adr(part.start)); int maxend = -1; + List catchedFinallys = new ArrayList<>(); List catchedExceptions = new ArrayList<>(); for (int e = 0; e < body.exceptions.length; e++) { if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) { @@ -200,11 +187,13 @@ public class AVM2Graph extends Graph { if (!parsedExceptions.contains(body.exceptions[e])) { if (((body.exceptions[e].end) > maxend)) { catchedExceptions.clear(); + catchedFinallys.clear(); maxend = this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end); catchedExceptions.add(body.exceptions[e]); } else if (this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) == maxend) { catchedExceptions.add(body.exceptions[e]); } + catchedFinallys.add(e); } } else if (body.exceptions[e].isFinally()) { @@ -233,14 +222,16 @@ public class AVM2Graph extends Graph { List finallyCommands = new ArrayList<>(); boolean hasFinally = false; int returnPos = afterCatchPos; + int finStart = -1; for (int e = 0; e < body.exceptions.length; e++) { if (body.exceptions[e].isFinally()) { if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) { if (afterCatchPos + 1 == code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))) { + catchedFinallys.add(e); AVM2Instruction jmpIns = this.avm2code.code.get(code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))); if (jmpIns.definition instanceof JumpIns) { - int finStart = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]); + finStart = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]); GraphPart fpart = null; for (GraphPart p : allParts) { @@ -249,6 +240,8 @@ public class AVM2Graph extends Graph { break; } } + TranslateStack st = (TranslateStack) stack.clone(); + st.clear(); int swPos = -1; for (int f = finStart; f < this.avm2code.code.size(); f++) { if (this.avm2code.code.get(f).definition instanceof LookupSwitchIns) { @@ -256,7 +249,7 @@ public class AVM2Graph extends Graph { if (swins.operands.length >= 3) { if (swins.operands[0] == swins.getBytes().length) { if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) { - stack.push(new ExceptionAVM2Item(body.exceptions[e])); + //st.push(new ExceptionAVM2Item(body.exceptions[e])); GraphPart fepart = null; for (GraphPart p : allParts) { if (p.start == f + 1) { @@ -280,13 +273,17 @@ public class AVM2Graph extends Graph { } //ignoredSwitches.add(-1); //int igs_size=ignoredSwitches.size(); - List oldFinallyJumps = new ArrayList<>(finallyJumps); + Map> oldFinallyJumps = new HashMap<>(finallyJumps); finallyJumps.clear(); - ignoredSwitches.add(swPos); - finallyCommands = printGraph(localData, stack, allParts, parent, fpart, null, loops, staticOperation, path); + ignoredSwitches.put(e, swPos); + st.push(new PopItem(null)); + finallyCommands = printGraph(localData, st, allParts, parent, fpart, null, loops, staticOperation, path); //ignoredSwitches.remove(igs_size-1); - finallyJumps.addAll(oldFinallyJumps); - finallyJumps.add(finStart); + finallyJumps.putAll(oldFinallyJumps); + if (!finallyJumps.containsKey(e)) { + finallyJumps.put(e, new ArrayList<>()); + } + finallyJumps.get(e).add(finStart); hasFinally = true; break; } @@ -328,7 +325,9 @@ public class AVM2Graph extends Graph { break; } } - stack.add(new ExceptionAVM2Item(catchedExceptions.get(e))); + TranslateStack st2 = (TranslateStack) stack.clone(); + st2.clear(); + st2.add(new ExceptionAVM2Item(catchedExceptions.get(e))); AVM2LocalData localData2 = new AVM2LocalData(aLocalData); localData2.scopeStack = new ScopeStack(); List stopPart2 = new ArrayList<>(stopPart); @@ -336,16 +335,18 @@ public class AVM2Graph extends Graph { if (retPart != null) { stopPart2.add(retPart); } - List ncatchedCommands = printGraph(localData2, stack, allParts, parent, npart, stopPart2, loops, staticOperation, path); + + List ncatchedCommands = printGraph(localData2, st2, allParts, parent, npart, stopPart2, loops, staticOperation, path); if (catchedExceptions.get(e).isFinally() && (catchedExceptions.size() > 1 || hasFinally)) { catchedExceptions.remove(e); e--; } else { catchedCommands.add(ncatchedCommands); if (retPart != null && avm2code.code.get(retPart.start).isExit() && !(!ncatchedCommands.isEmpty() && (ncatchedCommands.get(ncatchedCommands.size() - 1) instanceof ExitItem))) { - avm2code.code.get(retPart.start).translate(localData, stack, ncatchedCommands, staticOperation, path); + avm2code.code.get(retPart.start).translate(localData, st2, ncatchedCommands, staticOperation, path); } if (catchedExceptions.get(e).isFinally()) { + //endposStartBlock = -1; if (!ncatchedCommands.isEmpty() && (ncatchedCommands.get(0) instanceof SetLocalAVM2Item)) { SetLocalAVM2Item sl = (SetLocalAVM2Item) ncatchedCommands.get(0); if (sl.value.getNotCoerced() instanceof ExceptionAVM2Item) { @@ -364,19 +365,31 @@ public class AVM2Graph extends Graph { break; } } - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(nepart); + List stopPart2 = new ArrayList<>();//stopPart); + if (nepart != null) { + stopPart2.add(nepart); + } stopPart2.addAll(catchParts); if (retPart != null) { stopPart2.add(retPart); } - List tryCommands = printGraph(localData, stack, allParts, parent, part, stopPart2, loops, staticOperation, path); + TranslateStack st = (TranslateStack) stack.clone(); + st.clear(); + List tryCommands = printGraph(localData, st, allParts, parent, part, stopPart2, loops, staticOperation, path); if (retPart != null && avm2code.code.get(retPart.start).isExit() && !(!tryCommands.isEmpty() && (tryCommands.get(tryCommands.size() - 1) instanceof ExitItem))) { - avm2code.code.get(retPart.start).translate(localData, stack, tryCommands, staticOperation, path); + avm2code.code.get(retPart.start).translate(localData, st, tryCommands, staticOperation, path); } output.clear(); + stack.clear(); output.add(new TryAVM2Item(tryCommands, catchedExceptions, catchedCommands, finallyCommands, finCatchName)); + finallyJumps = ((AVM2LocalData) localData).finallyJumps; + for (int fin_e : catchedFinallys) { + if (finallyJumps.containsKey(fin_e)) { + finallyJumps.get(fin_e).clear(); + } + //.remove((Integer) finStart); + } ip = returnPos; } @@ -397,7 +410,10 @@ public class AVM2Graph extends Graph { ret.addAll(output); GraphTargetItem lop = checkLoop(part, stopPart, loops); if (lop == null) { - ret.addAll(printGraph(localData, stack, allParts, null, part, stopPart, loops, staticOperation, path)); + TranslateStack st = (TranslateStack) stack.clone(); + st.clear(); + + ret.addAll(printGraph(localData, st, allParts, null, part, stopPart, loops, staticOperation, path)); } else { ret.add(lop); } @@ -423,7 +439,7 @@ public class AVM2Graph extends Graph { } } } - if ((this.avm2code.code.get(part.end).definition instanceof LookupSwitchIns) && ignoredSwitches.contains(part.end)) { + if ((this.avm2code.code.get(part.end).definition instanceof LookupSwitchIns) && (ignoredSwitches.containsValue(part.end) || ignoredSwitches2.contains(part.end))) { ret = new ArrayList<>(); ret.addAll(output); return ret; @@ -444,9 +460,9 @@ public class AVM2Graph extends Graph { && (this.avm2code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns))) { if (stack.peek() instanceof StrictEqAVM2Item) { - ignoredSwitches.add(part.nextParts.get(0).nextParts.get(0).end); + ignoredSwitches2.add(part.nextParts.get(0).nextParts.get(0).end); } else { - ignoredSwitches.add(part.nextParts.get(1).nextParts.get(0).end); + ignoredSwitches2.add(part.nextParts.get(1).nextParts.get(0).end); } ret = new ArrayList<>(); ret.addAll(output); @@ -494,7 +510,7 @@ public class AVM2Graph extends Graph { } GraphPart numPart = part.nextParts.get(reversed ? 0 : 1); AVM2Instruction ins = null; - TranslateStack sstack = new TranslateStack(); + TranslateStack sstack = new TranslateStack(path); do { for (int n = 0; n < numPart.getHeight(); n++) { ins = this.avm2code.code.get(numPart.getPosAt(n)); @@ -535,7 +551,7 @@ public class AVM2Graph extends Graph { GraphPart numPart = dp; AVM2Instruction ins = null; - TranslateStack sstack = new TranslateStack(); + TranslateStack sstack = new TranslateStack(path); do { for (int n = 0; n < numPart.getHeight(); n++) { ins = this.avm2code.code.get(numPart.getPosAt(n)); @@ -636,33 +652,34 @@ public class AVM2Graph extends Graph { @Override protected GraphPart checkPart(TranslateStack stack, BaseLocalData localData, GraphPart next, List allParts) { AVM2LocalData aLocalData = (AVM2LocalData) localData; - List finallyJumps = aLocalData.finallyJumps; - List ignoredSwitches = aLocalData.ignoredSwitches; + Map> finallyJumps = aLocalData.finallyJumps; + Map ignoredSwitches = aLocalData.ignoredSwitches; GraphPart ret = next; - for (int f = 0; f < finallyJumps.size(); f++) { - int fip = finallyJumps.get(f); + for (int f : finallyJumps.keySet()) {//int f = 0; f < finallyJumps.size(); f++) { int swip = ignoredSwitches.get(f); - if (next.start == fip) { - if (stack != null && swip != -1) { - AVM2Instruction swIns = avm2code.code.get(swip); - GraphTargetItem t = stack.pop(); - Double dval = EcmaScript.toNumber(t.getResult()); - int val = (int) (double) dval; - if (swIns.definition instanceof LookupSwitchIns) { - List branches = swIns.getBranches(code); - int nip = branches.get(0); - if (val >= 0 && val < branches.size() - 1) { - nip = branches.get(1 + val); - } - for (GraphPart p : allParts) { - if (avm2code.fixIPAfterDebugLine(p.start) == avm2code.fixIPAfterDebugLine(nip)) { - return p; + for (int fip : finallyJumps.get(f)) { + if (next.start == fip) { + if (stack != null && swip != -1) { + AVM2Instruction swIns = avm2code.code.get(swip); + GraphTargetItem t = stack.pop(); + Double dval = EcmaScript.toNumber(t.getResult()); + int val = (int) (double) dval; + if (swIns.definition instanceof LookupSwitchIns) { + List branches = swIns.getBranches(code); + int nip = branches.get(0); + if (val >= 0 && val < branches.size() - 1) { + nip = branches.get(1 + val); } + for (GraphPart p : allParts) { + if (avm2code.fixIPAfterDebugLine(p.start) == avm2code.fixIPAfterDebugLine(nip)) { + return p; + } + } + ret = null; } - ret = null; } + ret = null; } - ret = null; } } if (ret != next) { @@ -678,8 +695,14 @@ public class AVM2Graph extends Graph { AVM2Instruction jmpIns = this.avm2code.code.get(avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))); if (jmpIns.definition instanceof JumpIns) { int finStart = avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]); - finallyJumps.add(finStart); - ignoredSwitches.add(-1); + if (!finallyJumps.containsKey(e)) { + finallyJumps.put(e, new ArrayList<>()); + } + finallyJumps.get(e).add(finStart); + if (!ignoredSwitches.containsKey(e)) { + ignoredSwitches.put(e, -1); + } + //ignoredSwitches.put(e, -1); break; } } @@ -707,7 +730,11 @@ public class AVM2Graph extends Graph { } GraphTargetItem ft = w.commands.get(pos); if (ft instanceof WithAVM2Item) { - ft = w.commands.get(pos + 1); + pos++; + while (w.commands.get(pos) instanceof SetTypeAVM2Item) { + pos++; + } + ft = w.commands.get(pos); if (ft instanceof IfItem) { IfItem ift = (IfItem) ft; if (ift.onTrue.size() > 0) { @@ -759,7 +786,7 @@ public class AVM2Graph extends Graph { @Override protected void finalProcess(List list, int level, FinalProcessLocalData localData) { - super.finalProcess(list, level, localData); + if (level == 0) { if (!list.isEmpty()) { if (list.get(list.size() - 1) instanceof ReturnVoidAVM2Item) { @@ -864,6 +891,8 @@ public class AVM2Graph extends Graph { } } } + //Handle for loops at the end: + super.finalProcess(list, level, localData); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/NotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/NotIns.java index f222a3d22..121344f18 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/NotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/NotIns.java @@ -1,49 +1,49 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.NotItem; -import java.util.HashMap; -import java.util.List; - -public class NotIns extends InstructionDefinition { - - public NotIns() { - super(0x96, "not", new int[]{}, false); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem v = stack.pop(); - stack.push(new NotItem(ins, v)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1 + 1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.NotItem; +import java.util.HashMap; +import java.util.List; + +public class NotIns extends InstructionDefinition { + + public NotIns() { + super(0x96, "not", new int[]{}, false); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem v = stack.pop(); + stack.push(v.invert(ins)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1 + 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfFalseIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfFalseIns.java index 1ac54af7a..e71bdb9e8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfFalseIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfFalseIns.java @@ -1,56 +1,57 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.NotItem; -import java.util.HashMap; -import java.util.List; - -public class IfFalseIns extends InstructionDefinition implements IfTypeIns { - - public IfFalseIns() { - super(0x12, "iffalse", new int[]{AVM2Code.DAT_OFFSET}, false); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem v1 = stack.pop(); - stack.push(new NotItem(ins, v1)); - } - - @Override - public void translateInverted(HashMap localRegs, TranslateStack stack, AVM2Instruction ins) { - //String v1 = stack.pop().toString(); - //stack.push("(" + v1 + ")"); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.NotItem; +import java.util.HashMap; +import java.util.List; + +public class IfFalseIns extends InstructionDefinition implements IfTypeIns { + + public IfFalseIns() { + super(0x12, "iffalse", new int[]{AVM2Code.DAT_OFFSET}, false); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem v1 = stack.pop(); + //stack.push(new NotItem(ins, v1)); + stack.push(v1.invert(ins)); + } + + @Override + public void translateInverted(HashMap localRegs, TranslateStack stack, AVM2Instruction ins) { + //String v1 = stack.pop().toString(); + //stack.push("(" + v1 + ")"); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfTrueIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfTrueIns.java index 8f61976f0..dd59e4687 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfTrueIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfTrueIns.java @@ -1,56 +1,56 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.NotItem; -import java.util.HashMap; -import java.util.List; - -public class IfTrueIns extends InstructionDefinition implements IfTypeIns { - - public IfTrueIns() { - super(0x11, "iftrue", new int[]{AVM2Code.DAT_OFFSET}, false); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - //String v1 = stack.pop().toString(); - //stack.push("(" + v1 + ")"); - } - - @Override - public void translateInverted(HashMap localRegs, TranslateStack stack, AVM2Instruction ins) { - GraphTargetItem v1 = stack.pop(); - stack.push(new NotItem(ins, v1)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.NotItem; +import java.util.HashMap; +import java.util.List; + +public class IfTrueIns extends InstructionDefinition implements IfTypeIns { + + public IfTrueIns() { + super(0x11, "iftrue", new int[]{AVM2Code.DAT_OFFSET}, false); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + //String v1 = stack.pop().toString(); + //stack.push("(" + v1 + ")"); + } + + @Override + public void translateInverted(HashMap localRegs, TranslateStack stack, AVM2Instruction ins) { + GraphTargetItem v1 = stack.pop(); + stack.push(v1.invert(null)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java index 973dcde54..85895b8e5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java @@ -1,134 +1,134 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.instructions.SetTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.DecrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.PostDecrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.PostIncrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreDecrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; -import java.util.Stack; - -public abstract class SetLocalTypeIns extends InstructionDefinition implements SetTypeIns { - - public SetLocalTypeIns(int instructionCode, String instructionName, int[] operands, boolean canThrow) { - super(instructionCode, instructionName, operands, canThrow); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap regAssignCount, int ip, HashMap> refs, AVM2Code code) { - int regId = getRegisterId(ins); - GraphTargetItem value = stack.pop(); - /*if (localRegs.containsKey(regId)) { - localRegs.put(regId, new NotCompileTimeAVM2Item(ins, value)); - } else { - localRegs.put(regId, value); - }*/ - localRegs.put(regId, value); - if (!regAssignCount.containsKey(regId)) { - regAssignCount.put(regId, 0); - } - regAssignCount.put(regId, regAssignCount.get(regId) + 1); - //localRegsAssignmentIps.put(regId, ip); - if (value instanceof NewActivationAVM2Item) { - return; - } - if (value instanceof FindPropertyAVM2Item) { - return; - } - if (value.getNotCoerced() instanceof IncrementAVM2Item) { - GraphTargetItem inside = ((IncrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate(); - if (inside instanceof LocalRegAVM2Item) { - if (((LocalRegAVM2Item) inside).regIndex == regId) { - if (stack.size() > 0) { - GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); - if (top == inside) { - stack.pop(); - stack.push(new PostIncrementAVM2Item(ins, inside)); - } else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).value == inside)) { - stack.pop(); - stack.push(new PreIncrementAVM2Item(ins, inside)); - } else { - output.add(new PostIncrementAVM2Item(ins, inside)); - } - } else { - output.add(new PostIncrementAVM2Item(ins, inside)); - } - return; - } - } - } - - if (value.getNotCoerced() instanceof DecrementAVM2Item) { - GraphTargetItem inside = ((DecrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate(); - if (inside instanceof LocalRegAVM2Item) { - if (((LocalRegAVM2Item) inside).regIndex == regId) { - if (stack.size() > 0) { - GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); - if (top == inside) { - stack.pop(); - stack.push(new PostDecrementAVM2Item(ins, inside)); - } else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).value == inside)) { - stack.pop(); - stack.push(new PreDecrementAVM2Item(ins, inside)); - } else { - output.add(new PostDecrementAVM2Item(ins, inside)); - } - } else { - output.add(new PostDecrementAVM2Item(ins, inside)); - } - return; - } - } - } - - //if(val.startsWith("catchscope ")) return; - //if(val.startsWith("newactivation()")) return; - output.add(new SetLocalAVM2Item(ins, regId, value)); - } - - @Override - public String getObject(Stack stack, ABC abc, AVM2Instruction ins, List output, MethodBody body, HashMap localRegNames, List fullyQualifiedNames) { - return AVM2Item.localRegName(localRegNames, getRegisterId(ins)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1; - } - - public abstract int getRegisterId(AVM2Instruction ins); -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.SetTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.DecrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.PostDecrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.PostIncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreDecrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; +import java.util.Stack; + +public abstract class SetLocalTypeIns extends InstructionDefinition implements SetTypeIns { + + public SetLocalTypeIns(int instructionCode, String instructionName, int[] operands, boolean canThrow) { + super(instructionCode, instructionName, operands, canThrow); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap regAssignCount, int ip, HashMap> refs, AVM2Code code) { + int regId = getRegisterId(ins); + GraphTargetItem value = stack.pop(); + /*if (localRegs.containsKey(regId)) { + localRegs.put(regId, new NotCompileTimeAVM2Item(ins, value)); + } else { + localRegs.put(regId, value); + }*/ + localRegs.put(regId, value); + if (!regAssignCount.containsKey(regId)) { + regAssignCount.put(regId, 0); + } + regAssignCount.put(regId, regAssignCount.get(regId) + 1); + //localRegsAssignmentIps.put(regId, ip); + if (value.getThroughDuplicate() instanceof NewActivationAVM2Item) { + return; + } + if (value instanceof FindPropertyAVM2Item) { + return; + } + if (value.getNotCoerced() instanceof IncrementAVM2Item) { + GraphTargetItem inside = ((IncrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate(); + if (inside instanceof LocalRegAVM2Item) { + if (((LocalRegAVM2Item) inside).regIndex == regId) { + if (stack.size() > 0) { + GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); + if (top == inside) { + stack.pop(); + stack.push(new PostIncrementAVM2Item(ins, inside)); + } else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).value == inside)) { + stack.pop(); + stack.push(new PreIncrementAVM2Item(ins, inside)); + } else { + output.add(new PostIncrementAVM2Item(ins, inside)); + } + } else { + output.add(new PostIncrementAVM2Item(ins, inside)); + } + return; + } + } + } + + if (value.getNotCoerced() instanceof DecrementAVM2Item) { + GraphTargetItem inside = ((DecrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate(); + if (inside instanceof LocalRegAVM2Item) { + if (((LocalRegAVM2Item) inside).regIndex == regId) { + if (stack.size() > 0) { + GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); + if (top == inside) { + stack.pop(); + stack.push(new PostDecrementAVM2Item(ins, inside)); + } else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).value == inside)) { + stack.pop(); + stack.push(new PreDecrementAVM2Item(ins, inside)); + } else { + output.add(new PostDecrementAVM2Item(ins, inside)); + } + } else { + output.add(new PostDecrementAVM2Item(ins, inside)); + } + return; + } + } + } + + //if(val.startsWith("catchscope ")) return; + //if(val.startsWith("newactivation()")) return; + output.add(new SetLocalAVM2Item(ins, regId, value)); + } + + @Override + public String getObject(Stack stack, ABC abc, AVM2Instruction ins, List output, MethodBody body, HashMap localRegNames, List fullyQualifiedNames) { + return AVM2Item.localRegName(localRegNames, getRegisterId(ins)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1; + } + + public abstract int getRegisterId(AVM2Instruction ins); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java index aceb9e46e..7456f9eea 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java @@ -156,9 +156,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { } } } - if (slotname == null) { - System.err.println("SLOT NOT FOUND"); - } + output.add(new SetSlotAVM2Item(ins, obj, slotname, value)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java index 4865b4ff0..9abebbaaf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java @@ -45,13 +45,9 @@ public class PopIns extends InstructionDefinition { @Override public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - if (stack.size() > 0) { - GraphTargetItem top = stack.pop(); - //Note: Commands like "5;" - numbers are unsupported as it collide with try..finally block decompilation. TODO: allow this somehow - - if (/*!(top instanceof IntegerValueAVM2Item) &&*/(!(top instanceof MarkItem))) { - output.add(top); - } + GraphTargetItem top = stack.pop(); + if ((!(top instanceof MarkItem))) { + output.add(top); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushFalseIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushFalseIns.java index 8c32f6243..76076797c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushFalseIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushFalseIns.java @@ -1,54 +1,55 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class PushFalseIns extends InstructionDefinition { - - public PushFalseIns() { - super(0x27, "pushfalse", new int[]{}, false); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - lda.operandStack.push(Boolean.FALSE); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - stack.push(new BooleanAVM2Item(ins, Boolean.FALSE)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.FalseItem; +import java.util.HashMap; +import java.util.List; + +public class PushFalseIns extends InstructionDefinition { + + public PushFalseIns() { + super(0x27, "pushfalse", new int[]{}, false); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + lda.operandStack.push(Boolean.FALSE); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + stack.push(new FalseItem(ins)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushTrueIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushTrueIns.java index dc86afa3f..f87e6bb8d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushTrueIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushTrueIns.java @@ -1,54 +1,55 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class PushTrueIns extends InstructionDefinition { - - public PushTrueIns() { - super(0x26, "pushtrue", new int[]{}, false); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - lda.operandStack.push(Boolean.TRUE); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - stack.push(new BooleanAVM2Item(ins, Boolean.TRUE)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.TrueItem; +import java.util.HashMap; +import java.util.List; + +public class PushTrueIns extends InstructionDefinition { + + public PushTrueIns() { + super(0x26, "pushtrue", new int[]{}, false); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + lda.operandStack.push(Boolean.TRUE); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + stack.push(new TrueItem(ins)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/HasNextAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/HasNextAVM2Item.java index 671975b7f..12e3ca6a2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/HasNextAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/HasNextAVM2Item.java @@ -40,9 +40,9 @@ public class HasNextAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - collection.toString(writer, localData); + collection.appendTo(writer, localData); writer.append(" hasNext "); - return object.toString(writer, localData); + return object.appendTo(writer, localData); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java index dbe0fc1de..ce7c35d1a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -25,6 +26,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -78,4 +80,5 @@ public class IntegerValueAVM2Item extends NumberValueAVM2Item { public boolean hasReturnValue() { return true; } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewActivationAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewActivationAVM2Item.java index b664e18ef..a182b93e9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewActivationAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewActivationAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; @@ -32,7 +33,7 @@ public class NewActivationAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) { - return writer.append("newactivation()"); + return writer.append("§§activation"); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NumberValueAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NumberValueAVM2Item.java index 40f114929..3375c588e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NumberValueAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NumberValueAVM2Item.java @@ -1,25 +1,32 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.graph.SimpleValue; -public abstract class NumberValueAVM2Item extends AVM2Item { +public abstract class NumberValueAVM2Item extends AVM2Item implements SimpleValue { public NumberValueAVM2Item(AVM2Instruction instruction) { super(instruction, PRECEDENCE_PRIMARY); } + + @Override + public boolean isSimpleValue() { + return true; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSlotAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSlotAVM2Item.java index 989735dc2..68256562d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSlotAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSlotAVM2Item.java @@ -46,14 +46,14 @@ public class SetSlotAVM2Item extends AVM2Item implements SetTypeAVM2Item, Assign @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - srcData.localName = slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false); + srcData.localName = slotName == null ? "/*UnknownSlot*/" : slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false); getName(writer, localData); writer.append(" = "); return value.toString(writer, localData); } public String getNameAsStr(LocalData localData) { - return slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false); + return slotName == null ? "/*UnknownSlot*/" : slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false); } public GraphTextWriter getName(GraphTextWriter writer, LocalData localData) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/StringAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/StringAVM2Item.java index c99741759..b2d84022a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/StringAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/StringAVM2Item.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -31,7 +32,7 @@ import com.jpexs.helpers.Helper; import java.util.List; import java.util.Set; -public class StringAVM2Item extends AVM2Item { +public class StringAVM2Item extends AVM2Item implements SimpleValue { public String value; @@ -71,4 +72,9 @@ public class StringAVM2Item extends AVM2Item { public boolean hasReturnValue() { return true; } + + @Override + public boolean isSimpleValue() { + return true; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/EqAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/EqAVM2Item.java index fae5ce3b2..fe2f677bd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/EqAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/EqAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -53,7 +54,7 @@ public class EqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new NeqAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GeAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GeAVM2Item.java index aaf861327..2fa46b963 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GeAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GeAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class GeAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new LtAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GtAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GtAVM2Item.java index 32ec2e1d1..bacf5fffa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GtAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GtAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class GtAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new LeAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LeAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LeAVM2Item.java index a65e4250a..017f5e700 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LeAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LeAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class LeAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new GtAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LtAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LtAVM2Item.java index bbfc82018..006d7b386 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LtAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LtAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class LtAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new GeAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NeqAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NeqAVM2Item.java index 8e920d6df..69fc52490 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NeqAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NeqAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -54,7 +55,7 @@ public class NeqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfCondit } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new EqAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictEqAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictEqAVM2Item.java index e61d1196e..e13bce5a9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictEqAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictEqAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -56,7 +57,7 @@ public class StrictEqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfC } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new StrictNeqAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictNeqAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictNeqAVM2Item.java index cea963789..82cdae968 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictNeqAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictNeqAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -49,7 +50,7 @@ public class StrictNeqAVM2Item extends BinaryOpItem implements LogicalOpItem, If } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new StrictEqAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index bb2148713..0aaf4f006 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -57,9 +57,11 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushWithIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; @@ -103,7 +105,6 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; 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.action.model.DirectValueActionItem; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; @@ -118,6 +119,7 @@ import com.jpexs.decompiler.graph.model.CommaExpressionItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.DoWhileItem; import com.jpexs.decompiler.graph.model.DuplicateItem; +import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.ForItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -125,6 +127,7 @@ import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; +import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; import com.jpexs.decompiler.graph.model.WhileItem; import java.io.ByteArrayOutputStream; @@ -161,6 +164,16 @@ public class AVM2SourceGenerator implements SourceGenerator { return new AVM2Instruction(0, def, operands); } + @Override + public List generate(SourceGeneratorLocalData localData, FalseItem item) throws CompilationException { + return GraphTargetItem.toSourceMerge(localData, this, ins(new PushFalseIns())); + } + + @Override + public List generate(SourceGeneratorLocalData localData, TrueItem item) throws CompilationException { + return GraphTargetItem.toSourceMerge(localData, this, ins(new PushTrueIns())); + } + public List generate(SourceGeneratorLocalData localData, GetDescendantsAVM2Item item) throws CompilationException { int[] nssa = new int[item.openedNamespaces.size()]; for (int i = 0; i < item.openedNamespaces.size(); i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java index d3d5d869f..1156095b9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java @@ -1,2344 +1,2128 @@ -/* The following code was generated by JFlex 1.6.0 */ - -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.parser.script; - -import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; -import java.util.Stack; - -/** - * This class is a scanner generated by - * JFlex 1.6.0 - * from the specification file - * C:/Projects/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/actionscript3_script.flex - */ -public final class ActionScriptLexer { - - /** - * This character denotes the end of file - */ - public static final int YYEOF = -1; - - /** - * initial size of the lookahead buffer - */ - private static final int ZZ_BUFFERSIZE = 16384; - - /** - * lexical states - */ - public static final int YYINITIAL = 0; - - public static final int STRING = 2; - - public static final int CHARLITERAL = 4; - - public static final int XMLOPENTAG = 6; - - public static final int XMLOPENTAGATTRIB = 8; - - public static final int XMLINSTROPENTAG = 10; - - public static final int XMLINSTRATTRIB = 12; - - public static final int XMLCDATA = 14; - - public static final int XMLCOMMENT = 16; - - public static final int XML = 18; - - public static final int OIDENTIFIER = 20; - - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l - * at the beginning of a line - * l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, - 8, 8, 9, 9, 10, 10 - }; - - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED - = "\11\0\1\13\1\2\1\113\1\3\1\1\22\0\1\13\1\14\1\33" - + "\1\0\1\6\1\110\1\105\1\34\1\76\1\77\1\5\1\45\1\103" - + "\1\15\1\11\1\4\1\35\3\41\4\42\2\21\1\17\1\102\1\12" - + "\1\32\1\16\1\23\1\111\1\27\1\20\1\25\1\26\1\43\1\20" - + "\2\10\1\74\4\10\1\75\5\10\1\30\3\10\1\37\2\10\1\24" - + "\1\46\1\31\1\107\1\10\1\0\1\52\1\50\1\54\1\63\1\44" - + "\1\40\1\73\1\66\1\61\1\10\1\53\1\64\1\71\1\57\1\56" - + "\1\67\1\10\1\51\1\55\1\60\1\62\1\72\1\65\1\36\1\70" - + "\1\10\1\100\1\106\1\101\1\104\6\0\1\113\41\0\1\47\2\0" - + "\1\6\12\0\1\6\1\0\1\22\2\0\1\6\5\0\2\6\1\112" - + "\24\6\1\0\37\6\1\0\u01ca\6\4\0\14\6\16\0\5\6\7\0" - + "\1\6\1\0\1\6\21\0\160\7\5\6\1\0\2\6\2\0\4\6" - + "\1\0\1\6\6\0\1\6\1\0\3\6\1\0\1\6\1\0\24\6" - + "\1\0\123\6\1\0\213\6\1\0\5\7\2\0\246\6\1\0\46\6" - + "\2\0\1\6\7\0\47\6\11\0\55\7\1\0\1\7\1\0\2\7" - + "\1\0\2\7\1\0\1\7\10\0\33\6\5\0\3\6\35\0\13\7" - + "\5\0\53\6\37\7\4\0\2\6\1\7\143\6\1\0\1\6\7\7" - + "\2\0\6\7\2\6\2\7\1\0\4\7\2\6\12\7\3\6\2\0" - + "\1\6\20\0\1\6\1\7\36\6\33\7\2\0\131\6\13\7\1\6" - + "\16\0\12\7\41\6\11\7\2\6\4\0\1\6\5\0\26\6\4\7" - + "\1\6\11\7\1\6\3\7\1\6\5\7\22\0\31\6\3\7\104\0" - + "\23\6\61\0\40\7\66\6\3\7\1\6\22\7\1\6\7\7\12\6" - + "\2\7\2\0\12\7\1\0\20\6\3\7\1\0\10\6\2\0\2\6" - + "\2\0\26\6\1\0\7\6\1\0\1\6\3\0\4\6\2\0\1\7" - + "\1\6\7\7\2\0\2\7\2\0\3\7\1\6\10\0\1\7\4\0" - + "\2\6\1\0\3\6\2\7\2\0\12\7\2\6\17\0\3\7\1\0" - + "\6\6\4\0\2\6\2\0\26\6\1\0\7\6\1\0\2\6\1\0" - + "\2\6\1\0\2\6\2\0\1\7\1\0\5\7\4\0\2\7\2\0" - + "\3\7\3\0\1\7\7\0\4\6\1\0\1\6\7\0\14\7\3\6" - + "\1\7\13\0\3\7\1\0\11\6\1\0\3\6\1\0\26\6\1\0" - + "\7\6\1\0\2\6\1\0\5\6\2\0\1\7\1\6\10\7\1\0" - + "\3\7\1\0\3\7\2\0\1\6\17\0\2\6\2\7\2\0\12\7" - + "\21\0\3\7\1\0\10\6\2\0\2\6\2\0\26\6\1\0\7\6" - + "\1\0\2\6\1\0\5\6\2\0\1\7\1\6\7\7\2\0\2\7" - + "\2\0\3\7\10\0\2\7\4\0\2\6\1\0\3\6\2\7\2\0" - + "\12\7\1\0\1\6\20\0\1\7\1\6\1\0\6\6\3\0\3\6" - + "\1\0\4\6\3\0\2\6\1\0\1\6\1\0\2\6\3\0\2\6" - + "\3\0\3\6\3\0\14\6\4\0\5\7\3\0\3\7\1\0\4\7" - + "\2\0\1\6\6\0\1\7\16\0\12\7\20\0\4\7\1\0\10\6" - + "\1\0\3\6\1\0\27\6\1\0\20\6\3\0\1\6\7\7\1\0" - + "\3\7\1\0\4\7\7\0\2\7\1\0\2\6\6\0\2\6\2\7" - + "\2\0\12\7\21\0\3\7\1\0\10\6\1\0\3\6\1\0\27\6" - + "\1\0\12\6\1\0\5\6\2\0\1\7\1\6\7\7\1\0\3\7" - + "\1\0\4\7\7\0\2\7\7\0\1\6\1\0\2\6\2\7\2\0" - + "\12\7\1\0\2\6\16\0\3\7\1\0\10\6\1\0\3\6\1\0" - + "\51\6\2\0\1\6\7\7\1\0\3\7\1\0\4\7\1\6\10\0" - + "\1\7\10\0\2\6\2\7\2\0\12\7\12\0\6\6\2\0\2\7" - + "\1\0\22\6\3\0\30\6\1\0\11\6\1\0\1\6\2\0\7\6" - + "\3\0\1\7\4\0\6\7\1\0\1\7\1\0\10\7\6\0\12\7" - + "\2\0\2\7\15\0\60\6\1\7\2\6\7\7\5\0\7\6\10\7" - + "\1\0\12\7\47\0\2\6\1\0\1\6\2\0\2\6\1\0\1\6" - + "\2\0\1\6\6\0\4\6\1\0\7\6\1\0\3\6\1\0\1\6" - + "\1\0\1\6\2\0\2\6\1\0\4\6\1\7\2\6\6\7\1\0" - + "\2\7\1\6\2\0\5\6\1\0\1\6\1\0\6\7\2\0\12\7" - + "\2\0\4\6\40\0\1\6\27\0\2\7\6\0\12\7\13\0\1\7" - + "\1\0\1\7\1\0\1\7\4\0\2\7\10\6\1\0\44\6\4\0" - + "\24\7\1\0\2\7\5\6\13\7\1\0\44\7\11\0\1\7\71\0" - + "\53\6\24\7\1\6\12\7\6\0\6\6\4\7\4\6\3\7\1\6" - + "\3\7\2\6\7\7\3\6\4\7\15\6\14\7\1\6\17\7\2\0" - + "\46\6\1\0\1\6\5\0\1\6\2\0\53\6\1\0\u014d\6\1\0" - + "\4\6\2\0\7\6\1\0\1\6\1\0\4\6\2\0\51\6\1\0" - + "\4\6\2\0\41\6\1\0\4\6\2\0\7\6\1\0\1\6\1\0" - + "\4\6\2\0\17\6\1\0\71\6\1\0\4\6\2\0\103\6\2\0" - + "\3\7\40\0\20\6\20\0\125\6\14\0\u026c\6\2\0\21\6\1\0" - + "\32\6\5\0\113\6\3\0\3\7\10\6\7\0\15\6\1\0\4\6" - + "\3\7\13\0\22\6\3\7\13\0\22\6\2\7\14\0\15\6\1\0" - + "\3\6\1\0\2\7\14\0\64\6\40\7\3\0\1\6\4\0\1\6" - + "\1\7\2\0\12\7\41\0\3\7\2\0\12\7\6\0\130\6\10\0" - + "\51\6\1\7\1\6\5\0\106\6\12\0\37\6\1\0\14\7\4\0" - + "\14\7\12\0\12\7\36\6\2\0\5\6\13\0\54\6\4\0\21\7" - + "\7\6\2\7\6\0\12\7\46\0\27\6\5\7\4\0\65\6\12\7" - + "\1\0\35\7\2\0\13\7\6\0\12\7\15\0\1\6\10\0\16\7" - + "\102\0\5\7\57\6\21\7\7\6\4\0\12\7\21\0\11\7\14\0" - + "\3\7\36\6\15\7\2\6\12\7\54\6\16\7\14\0\44\6\24\7" - + "\10\0\12\7\3\0\3\6\12\7\44\6\122\0\3\7\1\0\25\7" - + "\4\6\1\7\4\6\3\7\2\6\1\0\2\7\6\0\300\6\66\7" - + "\6\0\4\7\u0116\6\2\0\6\6\2\0\46\6\2\0\6\6\2\0" - + "\10\6\1\0\1\6\1\0\1\6\1\0\1\6\1\0\37\6\2\0" - + "\65\6\1\0\7\6\1\0\1\6\3\0\3\6\1\0\7\6\3\0" - + "\4\6\2\0\6\6\4\0\15\6\5\0\3\6\1\0\7\6\3\0" - + "\14\0\2\0\32\0\1\113\1\113\25\0\2\7\23\0\1\7\33\0" - + "\1\0\1\6\15\0\1\6\20\0\15\6\63\0\15\7\4\0\1\7" - + "\3\0\14\7\21\0\1\6\4\0\1\6\2\0\12\6\1\0\1\6" - + "\3\0\5\6\6\0\1\6\1\0\1\6\1\0\1\6\1\0\4\6" - + "\1\0\13\6\2\0\4\6\5\0\5\6\4\0\1\6\21\0\43\7" - + "\2\6\4\7\7\0\u0a70\0\57\6\1\0\57\6\1\0\205\6\6\0" - + "\4\6\3\7\2\6\14\0\46\6\1\0\1\6\5\0\1\6\2\0" - + "\70\6\7\0\1\6\17\0\1\7\27\6\11\0\7\6\1\0\7\6" - + "\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6" - + "\1\0\7\6\1\0\40\7\57\0\1\6\u01c0\0\21\0\4\0\2\6" - + "\1\7\31\0\17\7\1\0\5\6\2\0\3\7\2\6\4\0\126\6" - + "\2\0\2\7\2\0\3\6\1\0\132\6\1\0\4\6\5\0\51\6" - + "\3\0\136\6\21\0\33\6\65\0\20\6\u0200\0\u19b6\6\112\0\u51cd\6" - + "\63\0\u048d\6\103\0\56\6\2\0\u010d\6\3\0\20\6\12\7\2\6" - + "\24\0\57\6\1\7\4\0\12\7\1\0\37\6\1\0\1\7\106\6" - + "\14\7\45\0\11\6\2\0\147\6\2\0\4\6\1\0\36\6\2\0" - + "\2\6\105\0\13\6\1\7\3\6\1\7\4\6\1\7\27\6\5\7" - + "\30\0\64\6\14\0\2\7\62\6\21\7\13\0\12\7\6\0\22\7" - + "\6\6\3\0\1\6\4\0\12\7\34\6\10\7\2\0\27\6\15\7" - + "\14\0\35\6\3\0\4\7\57\6\16\7\16\0\1\6\12\7\6\0" - + "\5\6\1\7\12\6\12\7\5\6\1\0\51\6\16\7\11\0\3\6" - + "\1\7\10\6\2\7\2\0\12\7\6\0\27\6\3\0\1\6\3\7" - + "\62\6\1\7\1\6\3\7\2\6\2\7\5\6\2\7\1\6\1\7" - + "\1\6\30\0\3\6\2\0\13\6\5\7\2\0\3\6\2\7\12\0" - + "\6\6\2\0\6\6\2\0\6\6\11\0\7\6\1\0\7\6\1\0" - + "\53\6\1\0\4\6\4\0\2\6\132\0\43\6\10\7\1\0\2\7" - + "\2\0\12\7\6\0\u2ba4\6\14\0\27\6\4\0\61\6\4\0\u1800\0" - + "\u0900\0\u016e\6\2\0\152\6\46\0\7\6\14\0\5\6\5\0\1\6" - + "\1\7\12\6\1\0\15\6\1\0\5\6\1\0\1\6\1\0\2\6" - + "\1\0\2\6\1\0\154\6\41\0\u016b\6\22\0\100\6\2\0\66\6" - + "\10\0\40\0\14\6\4\0\20\7\20\0\16\7\5\0\2\7\30\0" - + "\3\7\40\0\5\6\1\0\207\6\23\0\12\7\7\0\32\6\4\0" - + "\1\7\1\0\32\6\13\0\131\6\3\0\6\6\2\0\6\6\2\0" - + "\6\6\2\0\3\6\41\0\2\0\14\6\1\0\32\6\1\0\23\6" - + "\1\0\2\6\1\0\17\6\2\0\16\6\42\0\173\6\105\0\65\7" - + "\210\0\1\7\202\0\35\6\3\0\61\6\17\0\1\7\37\0\40\6" - + "\20\0\21\6\1\7\10\6\1\7\5\0\46\6\5\7\5\0\36\6" - + "\2\0\44\6\4\0\10\6\1\0\5\7\52\0\236\6\2\0\12\7" - + "\126\0\50\6\10\0\64\6\234\0\u0137\6\11\0\26\6\12\0\10\6" - + "\230\0\6\6\2\0\1\6\1\0\54\6\1\0\2\6\3\0\1\6" - + "\2\0\27\6\12\0\27\6\11\0\37\6\141\0\26\6\12\0\32\6" - + "\106\0\70\6\6\0\2\6\100\0\1\6\3\7\1\0\2\7\5\0" - + "\4\7\4\6\1\0\3\6\1\0\33\6\4\0\3\7\4\0\1\7" - + "\40\0\35\6\3\0\35\6\43\0\10\6\1\0\34\6\2\7\31\0" - + "\66\6\12\0\26\6\12\0\23\6\15\0\22\6\156\0\111\6\u03b7\0" - + "\3\7\65\6\17\7\37\0\12\7\17\0\4\7\55\6\13\7\25\0" - + "\31\6\7\0\12\7\6\0\3\7\44\6\16\7\1\0\12\7\20\0" - + "\43\6\1\7\2\0\1\6\11\0\3\7\60\6\16\7\4\6\13\0" - + "\12\7\1\6\45\0\22\6\1\0\31\6\14\7\170\0\57\6\14\7" - + "\5\0\12\7\7\0\3\7\1\0\10\6\2\0\2\6\2\0\26\6" - + "\1\0\7\6\1\0\2\6\1\0\5\6\2\0\1\7\1\6\7\7" - + "\2\0\2\7\2\0\3\7\11\0\1\7\5\0\5\6\2\7\2\0" - + "\7\7\3\0\5\7\u010b\0\60\6\24\7\2\6\1\0\1\6\10\0" - + "\12\7\246\0\57\6\7\7\2\0\11\7\77\0\60\6\21\7\3\0" - + "\1\6\13\0\12\7\46\0\53\6\15\7\10\0\12\7\u01d6\0\100\6" - + "\12\7\25\0\1\6\u01c0\0\71\6\u0507\0\u0399\6\147\0\157\7\u0b91\0" - + "\u042f\6\u33d1\0\u0239\6\7\0\37\6\1\0\12\7\146\0\36\6\2\0" - + "\5\7\13\0\60\6\7\7\11\0\4\6\14\0\12\7\11\0\25\6" - + "\5\0\23\6\u0370\0\105\6\13\0\1\6\56\7\20\0\4\7\15\6" - + "\u4060\0\2\6\u0bfe\0\153\6\5\0\15\6\3\0\11\6\7\0\12\6" - + "\3\0\2\7\u14c6\0\5\7\3\0\6\7\10\0\10\7\2\0\7\7" - + "\36\0\4\7\224\0\3\7\u01bb\0\125\6\1\0\107\6\1\0\2\6" - + "\2\0\1\6\2\0\2\6\2\0\4\6\1\0\14\6\1\0\1\6" - + "\1\0\7\6\1\0\101\6\1\0\4\6\2\0\10\6\1\0\7\6" - + "\1\0\34\6\1\0\4\6\1\0\5\6\1\0\1\6\3\0\7\6" - + "\1\0\u0154\6\2\0\31\6\1\0\31\6\1\0\37\6\1\0\31\6" - + "\1\0\37\6\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6" - + "\1\0\31\6\1\0\10\6\2\0\62\7\u1000\0\305\6\13\0\7\7" - + "\u0529\0\4\6\1\0\33\6\1\0\2\6\1\0\1\6\2\0\1\6" - + "\1\0\12\6\1\0\4\6\1\0\1\6\1\0\1\6\6\0\1\6" - + "\4\0\1\6\1\0\1\6\1\0\1\6\1\0\3\6\1\0\2\6" - + "\1\0\1\6\2\0\1\6\1\0\1\6\1\0\1\6\1\0\1\6" - + "\1\0\1\6\1\0\2\6\1\0\1\6\2\0\4\6\1\0\7\6" - + "\1\0\4\6\1\0\4\6\1\0\1\6\1\0\12\6\1\0\21\6" - + "\5\0\3\6\1\0\5\6\1\0\21\6\u1144\0\ua6d7\6\51\0\u1035\6" - + "\13\0\336\6\u3fe2\0\u021e\6\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\u06ed\0" - + "\360\7\uffff\0\uffff\0\ufe12\0"; - - /** - * Translates characters to character classes - */ - private static final char[] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int[] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 - = "\13\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7" - + "\1\10\1\11\1\12\1\13\1\14\1\15\1\16\1\17" - + "\1\20\1\21\1\22\1\23\1\15\2\6\1\24\1\25" - + "\21\6\1\26\1\27\1\30\1\31\1\32\1\33\1\34" - + "\1\35\1\36\1\37\1\40\1\41\1\42\2\43\1\44" - + "\1\1\1\42\2\45\2\46\1\42\2\1\1\47\1\50" - + "\1\1\1\51\2\1\1\52\1\1\1\53\2\42\2\54" - + "\2\42\1\55\1\42\1\1\1\56\1\3\1\0\1\57" - + "\1\60\1\61\1\62\1\63\1\64\1\65\1\66\1\67" - + "\1\70\1\71\1\72\1\73\1\74\1\75\1\76\1\0" - + "\1\77\1\63\1\100\1\0\2\100\7\6\1\101\1\102" - + "\2\6\1\103\16\6\1\104\1\105\1\106\4\6\1\107" - + "\13\6\1\110\1\111\1\112\1\113\1\114\1\115\1\116" - + "\1\117\1\120\1\116\1\121\1\122\1\123\1\124\1\125" - + "\1\126\1\116\1\127\1\0\1\130\1\0\1\131\1\0" - + "\1\132\1\133\1\0\1\134\4\0\1\135\2\0\1\136" - + "\4\137\2\3\2\0\1\140\1\141\1\142\1\143\1\144" - + "\1\0\1\63\1\145\2\146\1\100\1\6\1\147\13\6" - + "\1\150\4\6\1\151\4\6\1\152\6\6\1\153\12\6" - + "\1\154\1\6\1\155\1\6\1\156\3\0\1\134\1\157" - + "\1\160\1\0\1\161\2\0\1\162\1\163\1\164\1\0" - + "\1\165\1\146\1\100\4\6\1\166\1\167\2\6\1\170" - + "\12\6\1\171\1\172\1\6\1\173\11\6\1\174\5\6" - + "\1\175\1\6\1\176\2\0\1\177\1\200\1\0\1\146" - + "\1\100\1\201\1\202\2\6\1\203\1\6\1\204\1\205" - + "\1\6\1\206\1\6\1\207\4\6\1\210\11\6\1\211" - + "\5\6\1\0\1\146\1\100\3\6\1\212\1\6\1\213" - + "\1\214\1\6\1\215\1\6\1\216\3\6\1\217\3\6" - + "\1\220\4\6\1\221\1\6\1\0\1\146\1\100\1\222" - + "\1\6\1\223\10\6\1\224\1\225\1\6\1\226\1\227" - + "\1\6\1\0\1\146\1\100\1\230\1\231\1\232\3\6" - + "\1\233\3\6\1\234\1\0\1\146\1\100\1\235\1\6" - + "\1\236\1\6\1\237\1\240\1\241\1\146\1\100\1\242" - + "\1\243\6\100"; - - private static int[] zzUnpackAction() { - int[] result = new int[446]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAction(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } - - /** - * Translates a state to a row index in the transition table - */ - private static final int[] ZZ_ROWMAP = zzUnpackRowMap(); - - private static final String ZZ_ROWMAP_PACKED_0 - = "\0\0\0\114\0\230\0\344\0\u0130\0\u017c\0\u01c8\0\u0214" - + "\0\u0260\0\u02ac\0\u02f8\0\u0344\0\u0390\0\u0344\0\u03dc\0\u0428" - + "\0\u0474\0\u04c0\0\u050c\0\u0558\0\u05a4\0\u05f0\0\u063c\0\u0688" - + "\0\u06d4\0\u0344\0\u0344\0\u0344\0\u0720\0\u0344\0\u0344\0\u076c" - + "\0\u07b8\0\u0804\0\u0850\0\u0344\0\u089c\0\u08e8\0\u0934\0\u0980" - + "\0\u09cc\0\u0a18\0\u0a64\0\u0ab0\0\u0afc\0\u0b48\0\u0b94\0\u0be0" - + "\0\u0c2c\0\u0c78\0\u0cc4\0\u0d10\0\u0d5c\0\u0344\0\u0344\0\u0344" - + "\0\u0344\0\u0344\0\u0344\0\u0344\0\u0da8\0\u0df4\0\u0e40\0\u0e8c" - + "\0\u0344\0\u0ed8\0\u0f24\0\u0344\0\u0344\0\u0f70\0\u0fbc\0\u1008" - + "\0\u0344\0\u1054\0\u0344\0\u10a0\0\u10ec\0\u1138\0\u0344\0\u0344" - + "\0\u1184\0\u0344\0\u11d0\0\u121c\0\u0344\0\u1268\0\u0344\0\u0344" - + "\0\u12b4\0\u1300\0\u0344\0\u134c\0\u1398\0\u0344\0\u13e4\0\u1430" - + "\0\u0344\0\u147c\0\u14c8\0\u0344\0\u0344\0\u1514\0\u0344\0\u1560" - + "\0\u0344\0\u15ac\0\u15f8\0\u0344\0\u0344\0\u1644\0\u0344\0\u0344" - + "\0\u1690\0\u0344\0\u0344\0\u16dc\0\u1728\0\u1774\0\u17c0\0\u180c" - + "\0\u1858\0\u18a4\0\u18f0\0\u193c\0\u1988\0\u19d4\0\u1a20\0\u1a6c" - + "\0\u1ab8\0\u0344\0\u0344\0\u1b04\0\u1b50\0\u04c0\0\u1b9c\0\u1be8" - + "\0\u1c34\0\u1c80\0\u1ccc\0\u1d18\0\u1d64\0\u1db0\0\u1dfc\0\u1e48" - + "\0\u1e94\0\u1ee0\0\u1f2c\0\u1f78\0\u04c0\0\u04c0\0\u1fc4\0\u2010" - + "\0\u205c\0\u20a8\0\u20f4\0\u04c0\0\u2140\0\u218c\0\u21d8\0\u2224" - + "\0\u2270\0\u22bc\0\u2308\0\u2354\0\u23a0\0\u23ec\0\u2438\0\u0344" - + "\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344" - + "\0\u2484\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u24d0" - + "\0\u0344\0\u1138\0\u0344\0\u1184\0\u0344\0\u11d0\0\u0344\0\u0344" - + "\0\u1268\0\u251c\0\u2568\0\u25b4\0\u2600\0\u264c\0\u2698\0\u26e4" - + "\0\u2730\0\u0344\0\u0344\0\u2484\0\u24d0\0\u277c\0\u27c8\0\u0344" - + "\0\u2814\0\u2860\0\u0344\0\u0344\0\u0344\0\u28ac\0\u0344\0\u28f8" - + "\0\u28f8\0\u0344\0\u2944\0\u180c\0\u2990\0\u29dc\0\u04c0\0\u2a28" - + "\0\u2a74\0\u2ac0\0\u2b0c\0\u2b58\0\u2ba4\0\u2bf0\0\u2c3c\0\u2c88" - + "\0\u2cd4\0\u2d20\0\u04c0\0\u2d6c\0\u2db8\0\u2e04\0\u2e50\0\u04c0" - + "\0\u2e9c\0\u2ee8\0\u2f34\0\u2f80\0\u04c0\0\u2fcc\0\u3018\0\u3064" - + "\0\u30b0\0\u30fc\0\u3148\0\u04c0\0\u3194\0\u31e0\0\u322c\0\u3278" - + "\0\u32c4\0\u3310\0\u335c\0\u33a8\0\u33f4\0\u3440\0\u04c0\0\u348c" - + "\0\u04c0\0\u34d8\0\u04c0\0\u3524\0\u3570\0\u251c\0\u0344\0\u0344" - + "\0\u0344\0\u35bc\0\u0344\0\u3608\0\u3654\0\u36a0\0\u0344\0\u0344" - + "\0\u36ec\0\u0344\0\u3738\0\u3784\0\u37d0\0\u381c\0\u3868\0\u38b4" - + "\0\u04c0\0\u04c0\0\u3900\0\u394c\0\u04c0\0\u3998\0\u39e4\0\u3a30" - + "\0\u3a7c\0\u3ac8\0\u3b14\0\u3b60\0\u3bac\0\u3bf8\0\u3c44\0\u04c0" - + "\0\u04c0\0\u3c90\0\u04c0\0\u3cdc\0\u3d28\0\u3d74\0\u3dc0\0\u3e0c" - + "\0\u3e58\0\u3ea4\0\u3ef0\0\u3f3c\0\u04c0\0\u3f88\0\u3fd4\0\u4020" - + "\0\u406c\0\u40b8\0\u04c0\0\u4104\0\u0344\0\u2484\0\u4150\0\u0344" - + "\0\u0344\0\u419c\0\u41e8\0\u4234\0\u04c0\0\u4280\0\u42cc\0\u4318" - + "\0\u04c0\0\u4364\0\u04c0\0\u04c0\0\u43b0\0\u04c0\0\u43fc\0\u04c0" - + "\0\u4448\0\u4494\0\u44e0\0\u452c\0\u04c0\0\u4578\0\u45c4\0\u4610" - + "\0\u465c\0\u46a8\0\u46f4\0\u4740\0\u478c\0\u47d8\0\u04c0\0\u4824" - + "\0\u4870\0\u48bc\0\u4908\0\u4954\0\u49a0\0\u49ec\0\u4a38\0\u4a84" - + "\0\u4ad0\0\u4b1c\0\u04c0\0\u4b68\0\u04c0\0\u04c0\0\u4bb4\0\u04c0" - + "\0\u4c00\0\u04c0\0\u4c4c\0\u4c98\0\u4ce4\0\u04c0\0\u4d30\0\u4d7c" - + "\0\u4dc8\0\u04c0\0\u4e14\0\u4e60\0\u4eac\0\u4ef8\0\u04c0\0\u4f44" - + "\0\u4f90\0\u4fdc\0\u5028\0\u04c0\0\u5074\0\u04c0\0\u50c0\0\u510c" - + "\0\u5158\0\u51a4\0\u51f0\0\u523c\0\u5288\0\u52d4\0\u04c0\0\u04c0" - + "\0\u5320\0\u04c0\0\u04c0\0\u536c\0\u53b8\0\u5404\0\u5450\0\u04c0" - + "\0\u04c0\0\u04c0\0\u549c\0\u54e8\0\u5534\0\u04c0\0\u5580\0\u55cc" - + "\0\u5618\0\u04c0\0\u5664\0\u56b0\0\u56fc\0\u04c0\0\u5748\0\u04c0" - + "\0\u5794\0\u04c0\0\u04c0\0\u0344\0\u0344\0\u57e0\0\u04c0\0\u04c0" - + "\0\u582c\0\u5878\0\u58c4\0\u5910\0\u595c\0\u1774"; - - private static int[] zzUnpackRowMap() { - int[] result = new int[446]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackRowMap(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); - } - return j; - } - - /** - * The transition table of the DFA - */ - private static final int[] ZZ_TRANS = zzUnpackTrans(); - - private static final String ZZ_TRANS_PACKED_0 - = "\1\14\1\15\1\16\1\17\1\20\1\21\1\22\1\14" - + "\1\22\1\23\1\24\1\17\1\25\1\26\1\27\1\30" - + "\1\22\1\31\1\14\1\32\1\33\4\22\1\34\1\35" - + "\1\36\1\37\1\40\2\22\1\41\2\31\1\22\1\42" - + "\1\43\1\14\1\44\1\45\1\46\1\47\1\22\1\50" - + "\1\51\1\52\1\53\1\54\1\55\1\56\1\57\1\22" - + "\1\60\1\22\1\61\2\22\1\62\1\63\1\64\1\65" - + "\1\66\1\67\1\70\1\71\1\72\1\73\1\74\1\75" - + "\1\76\1\77\1\100\1\101\1\22\1\14\1\102\1\103" - + "\1\104\30\102\1\105\12\102\1\106\45\102\1\107\1\110" - + "\1\111\31\107\1\105\11\107\1\106\45\107\1\14\1\112" - + "\1\113\1\114\1\115\3\14\1\116\2\14\1\114\2\14" - + "\1\117\2\116\4\14\4\116\5\14\3\116\2\14\2\116" - + "\3\14\26\116\2\14\1\120\46\14\1\121\44\14\1\122" - + "\14\14\1\112\1\113\1\114\4\14\1\123\2\14\1\114" - + "\3\14\2\123\2\14\1\124\1\14\4\123\5\14\3\123" - + "\2\14\2\123\3\14\26\123\2\14\1\125\46\14\1\126" - + "\44\14\1\127\13\14\1\130\1\112\1\113\26\130\1\131" - + "\63\130\1\132\1\133\12\130\1\134\77\130\1\112\1\113" - + "\7\130\1\135\65\130\1\136\13\130\1\137\1\110\1\111" - + "\43\137\1\140\1\141\44\137\116\0\1\16\114\0\1\17" - + "\7\0\1\17\104\0\1\142\1\143\24\0\1\144\113\0" - + "\1\145\67\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\26\22\14\0\1\22\12\0\1\146\1\147" - + "\6\0\1\150\13\0\1\150\3\0\2\150\33\0\1\151" - + "\25\0\1\152\1\0\1\153\4\0\2\152\4\0\4\152" - + "\1\0\1\154\3\0\3\152\2\0\2\152\3\0\26\152" - + "\2\0\1\155\45\0\1\156\76\0\1\157\14\0\1\160" - + "\77\0\1\161\13\0\1\162\100\0\1\163\105\0\1\150" - + "\7\0\1\31\13\0\1\31\3\0\2\31\2\164\101\0" - + "\1\165\72\0\1\150\7\0\1\166\13\0\1\167\2\170" - + "\1\0\1\171\1\172\2\164\55\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\2\22\1\173\3\22" - + "\1\174\2\22\1\175\1\176\13\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\1\22\1\177" - + "\6\22\3\0\2\22\1\200\11\22\1\201\11\22\14\0" - + "\1\22\33\0\1\202\12\0\1\203\54\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\1\22\1\204" - + "\24\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\205\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\5\22\1\206\20\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22" - + "\1\207\3\22\1\210\5\22\1\211\11\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\212\3\0\10\22\1\213\1\22\1\214\2\22\1\215" - + "\10\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\22\22\1\216\3\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\217\3\0\2\22\1\220\7\22\1\221\13\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\1\22\1\222\14\22\1\223\1\22" - + "\1\224\5\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\3\22\1\225\4\22\3\0\5\22" - + "\1\226\1\22\1\227\11\22\1\230\4\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\5\22\1\231\1\22\1\232\16\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\233\3\0\6\22\1\234\11\22\1\235\5\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\11\22\1\236\4\22\1\237\7\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\1\22\1\240\1\241\7\22\1\242\13\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\2\22\1\243\3\22\1\244\17\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\245\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\7\22\1\246\16\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\2\22\1\247" - + "\23\22\14\0\1\22\33\0\1\250\52\0\1\251\40\0" - + "\1\252\53\0\1\253\37\0\1\254\113\0\1\255\61\0" - + "\1\102\2\0\30\102\1\0\12\102\1\0\45\102\2\0" - + "\1\104\111\0\1\256\3\0\27\256\1\257\1\260\1\256" - + "\1\261\1\256\1\262\5\256\1\263\1\256\1\264\1\265" - + "\5\256\1\266\1\267\1\256\1\270\30\256\1\0\1\107" - + "\2\0\31\107\1\0\11\107\1\0\45\107\2\0\1\111" - + "\113\0\1\113\114\0\1\114\7\0\1\114\116\0\1\271" - + "\105\0\2\272\3\0\1\272\1\0\4\272\2\0\4\272" - + "\1\0\1\273\2\0\10\272\3\0\26\272\16\0\1\274" - + "\2\0\30\274\1\275\60\274\10\0\2\276\3\0\1\276" - + "\1\0\4\276\2\0\4\276\1\0\1\277\2\0\10\276" - + "\3\0\26\276\34\0\1\300\75\0\1\301\2\0\30\301" - + "\1\302\1\303\57\301\31\0\1\304\64\0\1\133\126\0" - + "\1\305\102\0\1\306\3\0\1\307\3\0\1\310\2\0" - + "\2\307\2\0\1\311\1\0\4\307\5\0\3\307\2\0" - + "\2\307\3\0\26\307\2\0\1\312\13\0\1\137\2\0" - + "\43\137\2\0\44\137\1\313\3\0\32\313\1\314\1\313" - + "\1\262\5\313\1\263\1\313\1\264\1\265\5\313\1\266" - + "\1\267\1\313\1\315\27\313\1\316\1\0\1\142\1\317" - + "\1\320\111\142\5\321\1\322\106\321\11\0\1\323\123\0" - + "\1\150\13\0\1\150\3\0\2\150\2\164\57\0\2\152" - + "\3\0\1\152\1\0\4\152\2\0\4\152\4\0\10\152" - + "\3\0\26\152\50\0\1\324\113\0\1\325\77\0\1\326" - + "\13\0\1\327\76\0\1\330\3\0\1\331\13\0\1\331" - + "\3\0\2\331\2\0\1\330\100\0\1\332\72\0\1\150" - + "\7\0\1\166\13\0\1\166\3\0\2\166\2\164\60\0" - + "\1\150\7\0\1\166\13\0\1\167\3\0\1\171\1\172" - + "\2\164\67\0\2\333\3\0\3\333\5\0\1\334\2\0" - + "\5\333\3\0\1\333\1\0\1\333\1\0\1\333\6\0" - + "\1\333\41\0\1\150\7\0\1\166\13\0\1\172\3\0" - + "\2\172\2\164\60\0\1\150\7\0\1\166\13\0\1\335" - + "\3\0\2\335\2\164\55\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\14\22\1\336\11\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\1\22\1\337\24\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\7\22\1\340\16\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\7\22\1\341" - + "\16\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\10\22\1\342\15\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\343\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\5\22\1\344\20\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\7\22\1\345\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\10\22\1\346\15\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\5\22\1\347\2\22\1\350\15\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\7\22\1\351\16\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22" - + "\1\352\23\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\10\22\1\353\15\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\2\22\1\354\23\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\17\22\1\355\6\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\11\22" - + "\1\356\14\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\7\22\1\357\3\0\26\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\15\22\1\360\10\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\10\22\1\361\10\22\1\362\4\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\14\22\1\363\11\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\12\22\1\364" - + "\5\22\1\365\5\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\1\22\1\366" - + "\7\22\1\367\14\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\17\22\1\370" - + "\6\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\5\22\1\371\2\22\1\372" - + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\17\22\1\373\6\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\374\3\0\26\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\13\22" - + "\1\375\12\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\3\22\1\376\4\22\3\0\14\22" - + "\1\377\11\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\7\22\1\u0100\16\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\10\22\1\u0101\15\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\11\22\1\u0102\14\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\6\22" - + "\1\u0103\2\22\1\u0104\14\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\4\22" - + "\1\u0105\21\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\1\u0106\25\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\1\22\1\u0107\24\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\11\22\1\u0108\14\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u0109" - + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\3\22\1\u010a\4\22\3\0\26\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\25\22\1\u010b\14\0\1\22\21\0\2\u010c" - + "\3\0\3\u010c\5\0\1\u010c\2\0\5\u010c\3\0\1\u010c" - + "\1\0\1\u010c\1\0\1\u010c\6\0\1\u010c\50\0\2\u010d" - + "\3\0\3\u010d\5\0\1\u010d\2\0\5\u010d\3\0\1\u010d" - + "\1\0\1\u010d\1\0\1\u010d\6\0\1\u010d\30\0\1\u010e" - + "\2\0\30\u010e\1\302\1\0\57\u010e\1\303\2\0\30\303" - + "\1\u010f\60\303\16\0\1\u0110\113\0\1\u0111\105\0\1\u0112" - + "\6\0\2\u0112\4\0\4\u0112\5\0\3\u0112\2\0\2\u0112" - + "\3\0\26\u0112\2\0\1\u0113\23\0\2\307\3\0\1\307" - + "\1\0\4\307\2\0\4\307\4\0\10\307\3\0\26\307" - + "\33\0\1\u0114\6\0\1\u0115\77\0\1\u0116\6\0\2\u0116" - + "\4\0\4\u0116\5\0\3\u0116\2\0\2\u0116\3\0\26\u0116" - + "\2\0\1\u0117\62\0\1\u0118\46\0\1\320\111\0\5\321" - + "\1\u0119\106\321\4\0\1\320\1\322\140\0\1\u011a\102\0" - + "\1\331\13\0\1\331\3\0\2\331\71\0\2\u011b\3\0" - + "\3\u011b\5\0\1\u011b\2\0\5\u011b\3\0\1\u011b\1\0" - + "\1\u011b\1\0\1\u011b\6\0\1\u011b\41\0\1\150\7\0" - + "\1\166\13\0\1\u011c\3\0\2\u011c\2\164\55\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\5\22" - + "\1\u011d\20\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u011e\23\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\4\22\1\u011f\21\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\u0120\3\0\26\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\16\22\1\u0121" - + "\7\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\u0122\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\2\22\1\u0123\23\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\12\22" - + "\1\u0124\13\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\7\22\1\u0125\3\0\26\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\u0126\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\5\22\1\u0127\2\22\1\u0128\15\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\5\22\1\u0129\20\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u012a" - + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\u012b\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\10\22\1\u012c\15\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\1\22" - + "\1\u012d\24\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\11\22\1\u012e\14\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\u012f\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\14\22\1\u0130\11\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\7\22\1\u0131\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\6\22\1\u0132\17\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\5\22\1\u0133\20\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u0134\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\10\22\1\u0135\15\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\u0136\3\0\26\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\6\22" - + "\1\u0137\5\22\1\u0138\11\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u0139\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\2\22\1\u013a\23\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\u013b\3\0\26\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22" - + "\1\u013c\23\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\16\22\1\u013d\7\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\14\22\1\u013e\11\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\10\22\1\u013f\15\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\22\22" - + "\1\u0140\3\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\3\22\1\u0141\22\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\14\22\1\u0142\11\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\13\22\1\u0143\12\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\11\22" - + "\1\u0144\14\22\14\0\1\22\21\0\2\u0145\3\0\3\u0145" - + "\5\0\1\u0145\2\0\5\u0145\3\0\1\u0145\1\0\1\u0145" - + "\1\0\1\u0145\6\0\1\u0145\50\0\2\u0146\3\0\3\u0146" - + "\5\0\1\u0146\2\0\5\u0146\3\0\1\u0146\1\0\1\u0146" - + "\1\0\1\u0146\6\0\1\u0146\31\0\2\u0147\5\0\2\u0112" - + "\1\0\1\u0147\1\0\1\u0112\1\u0148\4\u0112\2\0\4\u0112" - + "\4\0\10\u0112\3\0\26\u0112\33\0\1\u0149\123\0\1\u014a" - + "\76\0\2\u0116\3\0\1\u0116\1\0\4\u0116\2\0\4\u0116" - + "\4\0\10\u0116\3\0\26\u0116\16\0\4\321\1\320\1\u0119" - + "\106\321\20\0\2\u014b\3\0\3\u014b\5\0\1\u014b\2\0" - + "\5\u014b\3\0\1\u014b\1\0\1\u014b\1\0\1\u014b\6\0" - + "\1\u014b\41\0\1\150\7\0\1\166\13\0\1\u014c\3\0" - + "\2\u014c\2\164\55\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\u014d\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\14\22\1\u014e\11\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u014f" - + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\7\22\1\u0150\16\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\3\22\1\u0151\22\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\1\22\1\u0152\24\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\16\22\1\u0153" - + "\7\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\10\22\1\u0154\15\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\11\22\1\u0155\14\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\5\22\1\u0156\20\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\11\22\1\u0157" - + "\14\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\1\22\1\u0158\24\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\u0159\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\1\22\1\u015a\24\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\22\22\1\u015b" - + "\3\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\5\22\1\u015c\20\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\15\22\1\u015d\10\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\6\22\1\u015e\17\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\2\22\1\u015f" - + "\23\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\1\22\1\u0160\24\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\1\22\1\u0161\24\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u0162" - + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\3\22\1\u0163\4\22\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\12\22\1\u0164\13\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\10\22\1\u0165\15\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\21\22" - + "\1\u0166\4\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\7\22\1\u0167\3\0\26\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\u0168\3\0\26\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22" - + "\1\u0169\23\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u016a\23\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\11\22\1\u016b\14\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\7\22\1\u016c\16\22\14\0\1\22\2\0\2\u0147" - + "\10\0\1\u0147\2\0\1\u0148\123\0\1\u016d\105\0\2\u016e" - + "\3\0\3\u016e\5\0\1\u016e\2\0\5\u016e\3\0\1\u016e" - + "\1\0\1\u016e\1\0\1\u016e\6\0\1\u016e\41\0\1\150" - + "\7\0\1\166\13\0\1\u016f\3\0\2\u016f\2\164\55\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\14\22\1\u0170\11\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\11\22\1\u0171" - + "\14\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\13\22\1\u0172\12\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\7\22\1\u0173\16\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\7\22\1\u0174\16\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\4\22\1\u0175" - + "\21\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\16\22\1\u0176\7\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\11\22\1\u0177\14\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u0178" - + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\17\22\1\u0179\6\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\3\22\1\u017a\4\22\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\7\22\1\u017b\16\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\3\22\1\u017c\4\22" - + "\3\0\7\22\1\u017d\16\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22" - + "\1\u017e\15\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\21\22\1\u017f\4\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\11\22\1\u0180\14\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\14\22\1\u0181\11\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u0182\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\11\22\1\u0183\14\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\u0184\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\10\22\1\u0185\15\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\23\22\1\u0186" - + "\2\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\4\22\1\u0187\21\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\11\22\1\u0188\14\22\14\0\1\22\30\0" - + "\1\u0189\104\0\2\u018a\3\0\3\u018a\5\0\1\u018a\2\0" - + "\5\u018a\3\0\1\u018a\1\0\1\u018a\1\0\1\u018a\6\0" - + "\1\u018a\41\0\1\150\7\0\1\166\13\0\1\u018b\3\0" - + "\2\u018b\2\164\55\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\20\22\1\u018c\5\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\6\22\1\u018d\17\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\5\22" - + "\1\u018e\20\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\12\22\1\u018f\13\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\13\22\1\u0190\12\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\2\22\1\u0191\23\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\4\22" - + "\1\u0192\21\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u0193\23\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\2\22\1\u0194\23\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\u0195\3\0\26\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\7\22\1\u0196" - + "\16\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\10\22\1\u0197\15\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\u0198\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\10\22\1\u0199\15\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\7\22\1\u019a\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\u019b\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\10\22\1\u019c\15\22\14\0\1\22\31\0\1\u019d\103\0" - + "\2\u019e\3\0\3\u019e\5\0\1\u019e\2\0\5\u019e\3\0" - + "\1\u019e\1\0\1\u019e\1\0\1\u019e\6\0\1\u019e\41\0" - + "\1\150\7\0\1\166\13\0\1\u019f\3\0\2\u019f\2\164" - + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\7\22\1\u01a0\16\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u01a1\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\u01a2\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\4\22\1\u01a3\21\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u01a4\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\4\22\1\u01a5\21\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\14\22\1\u01a6\11\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\7\22\1\u01a7\16\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\7\22\1\u01a8\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\u01a9\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\20\22\1\u01aa\5\22\14\0\1\22\30\0\1\u01ab\104\0" - + "\2\u01ac\3\0\3\u01ac\5\0\1\u01ac\2\0\5\u01ac\3\0" - + "\1\u01ac\1\0\1\u01ac\1\0\1\u01ac\6\0\1\u01ac\41\0" - + "\1\150\7\0\1\166\13\0\1\u01ad\3\0\2\u01ad\2\164" - + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\u01ae\3\0\26\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\6\22\1\u01af" - + "\17\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\u01b0\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\10\22\1\u01b1\15\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\13\22" - + "\1\u01b2\12\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\13\22\1\u01b3\12\22" - + "\14\0\1\22\25\0\1\u01b4\107\0\2\u01b5\3\0\3\u01b5" - + "\5\0\1\u01b5\2\0\5\u01b5\3\0\1\u01b5\1\0\1\u01b5" - + "\1\0\1\u01b5\6\0\1\u01b5\41\0\1\150\7\0\1\166" - + "\13\0\1\u01b6\3\0\2\u01b6\2\164\55\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\3\22\1\u01b7\4\22\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\5\22\1\u01b8\20\22\14\0" - + "\1\22\12\0\1\150\7\0\1\166\13\0\1\u01b9\3\0" - + "\2\u01b9\2\164\60\0\1\150\7\0\1\166\13\0\1\u01ba" - + "\3\0\2\u01ba\2\164\60\0\1\150\7\0\1\166\13\0" - + "\1\u01bb\3\0\2\u01bb\2\164\60\0\1\150\7\0\1\166" - + "\13\0\1\u01bc\3\0\2\u01bc\2\164\60\0\1\150\7\0" - + "\1\166\13\0\1\u01bd\3\0\2\u01bd\2\164\60\0\1\150" - + "\7\0\1\166\13\0\1\u01be\3\0\2\u01be\2\164\47\0"; - - private static int[] zzUnpackTrans() { - int[] result = new int[22952]; - int offset = 0; - offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackTrans(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - value--; - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } - - - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; - - private static final int ZZ_NO_MATCH = 1; - - private static final int ZZ_PUSHBACK_2BIG = 2; - - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; - - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute(); - - private static final String ZZ_ATTRIBUTE_PACKED_0 - = "\13\0\1\11\1\1\1\11\13\1\3\11\1\1\2\11" - + "\4\1\1\11\21\1\7\11\4\1\1\11\2\1\2\11" - + "\3\1\1\11\1\1\1\11\3\1\2\11\1\1\1\11" - + "\2\1\1\11\1\1\2\11\2\1\1\11\2\1\1\11" - + "\2\1\1\11\1\1\1\0\2\11\1\1\1\11\1\1" - + "\1\11\2\1\2\11\1\1\2\11\1\1\2\11\1\0" - + "\3\1\1\0\11\1\2\11\44\1\11\11\1\1\6\11" - + "\1\1\1\11\1\0\1\11\1\0\1\11\1\0\2\11" - + "\1\0\1\1\4\0\1\1\2\0\2\11\4\1\1\11" - + "\2\0\3\11\1\1\1\11\1\0\1\1\1\11\61\1" - + "\3\0\3\11\1\0\1\11\2\0\1\1\2\11\1\0" - + "\1\11\52\1\1\11\2\0\2\11\1\0\42\1\1\0" - + "\33\1\1\0\23\1\1\0\15\1\1\0\10\1\2\11" - + "\11\1"; - - private static int[] zzUnpackAttribute() { - int[] result = new int[446]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAttribute(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } - - /** - * the input device - */ - private java.io.Reader zzReader; - - /** - * the current state of the DFA - */ - private int zzState; - - /** - * the current lexical state - */ - private int zzLexicalState = YYINITIAL; - - /** - * this buffer contains the current text to be matched and is - * the source of the yytext() string - */ - private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - - /** - * the textposition at the last accepting state - */ - private int zzMarkedPos; - - /** - * the current text position in the buffer - */ - private int zzCurrentPos; - - /** - * startRead marks the beginning of the yytext() string in the buffer - */ - private int zzStartRead; - - /** - * endRead marks the last character in the buffer, that has been read - * from input - */ - private int zzEndRead; - - /** - * number of newlines encountered up to the start of the matched text - */ - private int yyline; - - /** - * the number of characters up to the start of the matched text - */ - private int yychar; - - /** - * the number of characters from the last newline up to the start of the - * matched text - */ - private int yycolumn; - - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; - - /** - * zzAtEOF == true <=> the scanner is at the EOF - */ - private boolean zzAtEOF; - - /** - * denotes if the user-EOF-code has already been executed - */ - private boolean zzEOFDone; - - /** - * The number of occupied positions in zzBuffer beyond zzEndRead. - * When a lead/high surrogate has been read from the input stream - * into the final zzBuffer position, this will have a value of 1; - * otherwise, it will have a value of 0. - */ - private int zzFinalHighSurrogate = 0; - - /* user code: */ - private String sourceCode; - - public ActionScriptLexer(String sourceCode) { - this(new StringReader(sourceCode)); - this.sourceCode = sourceCode; - } - - public void yypushbackstr(String s, int state) { - sourceCode = s + sourceCode.substring(yychar + yylength()); - yyreset(new StringReader(sourceCode)); - yybegin(state); - } - - public void yypushbackstr(String s) { - yypushbackstr(s, YYINITIAL); - } - - StringBuffer string = new StringBuffer(); - - private static String xmlTagName = ""; - - public int yychar() { - return yychar; - } - - private Stack pushedBack = new Stack<>(); - - public int yyline() { - return yyline + 1; - } - - private List listeners = new ArrayList<>(); - - public void addListener(LexListener listener) { - listeners.add(listener); - } - - public void removeListener(LexListener listener) { - listeners.remove(listener); - } - - public void informListenersLex(ParsedSymbol s) { - for (LexListener l : listeners) { - l.onLex(s); - } - } - - public void informListenersPushBack(ParsedSymbol s) { - for (LexListener l : listeners) { - l.onPushBack(s); - } - } - - public void pushback(ParsedSymbol symb) { - pushedBack.push(symb); - last = null; - informListenersPushBack(symb); - } - - ParsedSymbol last; - - public ParsedSymbol lex() throws java.io.IOException, AVM2ParseException { - ParsedSymbol ret = null; - if (!pushedBack.isEmpty()) { - ret = last = pushedBack.pop(); - } else { - ret = last = yylex(); - } - informListenersLex(ret); - return ret; - } - - /** - * Creates a new scanner - * - * @param in the java.io.Reader to read input from. - */ - public ActionScriptLexer(java.io.Reader in) { - this.zzReader = in; - } - - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char[] zzUnpackCMap(String packed) { - char[] map = new char[0x110000]; - int i = 0; /* index in packed string */ - - int j = 0; /* index in unpacked array */ - - while (i < 3140) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do { - map[j++] = value; - } while (--count > 0); - } - return map; - } - - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { - - /* first: make room (if you can) */ - if (zzStartRead > 0) { - zzEndRead += zzFinalHighSurrogate; - zzFinalHighSurrogate = 0; - System.arraycopy(zzBuffer, zzStartRead, - zzBuffer, 0, - zzEndRead - zzStartRead); - - /* translate stored positions */ - zzEndRead -= zzStartRead; - zzCurrentPos -= zzStartRead; - zzMarkedPos -= zzStartRead; - zzStartRead = 0; - } - - /* is the buffer big enough? */ - if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { - /* if not: blow it up */ - char newBuffer[] = new char[zzBuffer.length * 2]; - System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); - zzBuffer = newBuffer; - zzEndRead += zzFinalHighSurrogate; - zzFinalHighSurrogate = 0; - } - - /* fill the buffer with new input */ - int requested = zzBuffer.length - zzEndRead; - int totalRead = 0; - while (totalRead < requested) { - int numRead = zzReader.read(zzBuffer, zzEndRead + totalRead, requested - totalRead); - if (numRead == -1) { - break; - } - totalRead += numRead; - } - - if (totalRead > 0) { - zzEndRead += totalRead; - if (totalRead == requested) { /* possibly more input available */ - - if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { - --zzEndRead; - zzFinalHighSurrogate = 1; - } - } - return false; - } - - // totalRead = 0: End of stream - return true; - } - - /** - * Closes the input stream. - */ - public final void yyclose() throws java.io.IOException { - zzAtEOF = true; /* indicate end of file */ - - zzEndRead = zzStartRead; /* invalidate buffer */ - - if (zzReader != null) { - zzReader.close(); - } - } - - /** - * Resets the scanner to read from a new input stream. - * Does not close the old reader. - * - * All internal variables are reset, the old input stream - * cannot be reused (internal buffer is discarded and lost). - * Lexical state is set to ZZ_INITIAL. - * - * Internal scan buffer is resized down to its initial length, if it has - * grown. - * - * @param reader the new input stream - */ - public final void yyreset(java.io.Reader reader) { - zzReader = reader; - zzAtBOL = true; - zzAtEOF = false; - zzEOFDone = false; - zzEndRead = zzStartRead = 0; - zzCurrentPos = zzMarkedPos = 0; - zzFinalHighSurrogate = 0; - yyline = yychar = yycolumn = 0; - zzLexicalState = YYINITIAL; - if (zzBuffer.length > ZZ_BUFFERSIZE) { - zzBuffer = new char[ZZ_BUFFERSIZE]; - } - } - - /** - * Returns the current lexical state. - */ - public final int yystate() { - return zzLexicalState; - } - - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } - - /** - * Returns the text matched by the current regular expression. - */ - public final String yytext() { - return new String(zzBuffer, zzStartRead, zzMarkedPos - zzStartRead); - } - - /** - * Returns the character at position pos from the - * matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. - * A value from 0 to yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer[zzStartRead + pos]; - } - - /** - * Returns the length of the matched text region. - */ - public final int yylength() { - return zzMarkedPos - zzStartRead; - } - - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method - * will only be called with things that "Can't Possibly Happen". - * If this method is called, something is seriously wrong - * (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done - * in error fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; - } catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; - } - - throw new Error(message); - } - - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. - * This number must not be greater than yylength()! - */ - public void yypushback(int number) { - if (number > yylength()) { - zzScanError(ZZ_PUSHBACK_2BIG); - } - - zzMarkedPos -= number; - } - - /** - * Resumes scanning until the next regular expression is matched, - * the end of input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - */ - public ParsedSymbol yylex() throws java.io.IOException, AVM2ParseException { - int zzInput; - int zzAction; - - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - char[] zzBufferL = zzBuffer; - char[] zzCMapL = ZZ_CMAP; - - int[] zzTransL = ZZ_TRANS; - int[] zzRowMapL = ZZ_ROWMAP; - int[] zzAttrL = ZZ_ATTRIBUTE; - - while (true) { - zzMarkedPosL = zzMarkedPos; - - yychar += zzMarkedPosL - zzStartRead; - - zzAction = -1; - - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - - zzState = ZZ_LEXSTATE[zzLexicalState]; - - // set up zzAction for empty match case: - int zzAttributes = zzAttrL[zzState]; - if ((zzAttributes & 1) == 1) { - zzAction = zzState; - } - - zzForAction: - { - while (true) { - - if (zzCurrentPosL < zzEndReadL) { - zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); - zzCurrentPosL += Character.charCount(zzInput); - } else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } else { - zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); - zzCurrentPosL += Character.charCount(zzInput); - } - } - int zzNext = zzTransL[zzRowMapL[zzState] + zzCMapL[zzInput]]; - if (zzNext == -1) { - break zzForAction; - } - zzState = zzNext; - - zzAttributes = zzAttrL[zzState]; - if ((zzAttributes & 1) == 1) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ((zzAttributes & 8) == 8) { - break zzForAction; - } - } - - } - } - - // store back cached position - zzMarkedPos = zzMarkedPosL; - - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 1: { - } - case 164: - break; - case 2: { - yyline++; - } - case 165: - break; - case 3: { /*ignore*/ - - } - case 166: - break; - case 4: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); - } - case 167: - break; - case 5: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); - } - case 168: - break; - case 6: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); - } - case 169: - break; - case 7: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); - } - case 170: - break; - case 8: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); - } - case 171: - break; - case 9: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); - } - case 172: - break; - case 10: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); - } - case 173: - break; - case 11: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); - } - case 174: - break; - case 12: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); - } - case 175: - break; - case 13: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); - } - case 176: - break; - case 14: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); - } - case 177: - break; - case 15: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); - } - case 178: - break; - case 16: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); - } - case 179: - break; - case 17: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); - } - case 180: - break; - case 18: { - string.setLength(0); - yybegin(STRING); - } - case 181: - break; - case 19: { - string.setLength(0); - yybegin(CHARLITERAL); - } - case 182: - break; - case 20: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); - } - case 183: - break; - case 21: { - string.setLength(0); - yybegin(OIDENTIFIER); - } - case 184: - break; - case 22: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); - } - case 185: - break; - case 23: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); - } - case 186: - break; - case 24: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); - } - case 187: - break; - case 25: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); - } - case 188: - break; - case 26: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); - } - case 189: - break; - case 27: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); - } - case 190: - break; - case 28: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); - } - case 191: - break; - case 29: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); - } - case 192: - break; - case 30: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); - } - case 193: - break; - case 31: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); - } - case 194: - break; - case 32: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); - } - case 195: - break; - case 33: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); - } - case 196: - break; - case 34: { - string.append(yytext()); - } - case 197: - break; - case 35: { - yybegin(YYINITIAL); - yyline++; - } - case 198: - break; - case 36: { - yybegin(YYINITIAL); - // length also includes the trailing quote - return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); - } - case 199: - break; - case 37: { - yybegin(YYINITIAL); - yyline++; - } - case 200: - break; - case 38: { - string.append(yytext()); - yyline++; - } - case 201: - break; - case 39: { - yybegin(XML); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_END, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 202: - break; - case 40: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRNAMEVAR_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 203: - break; - case 41: { - yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRVALVAR_BEGIN, yytext()); - } - case 204: - break; - case 42: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRNAMEVAR_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 205: - break; - case 43: { - yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRVALVAR_BEGIN, yytext()); - } - case 206: - break; - case 44: { - string.append(yytext()); - yyline++; - } - case 207: - break; - case 45: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_VAR_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 208: - break; - case 46: { - yybegin(YYINITIAL); - // length also includes the trailing quote - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); - } - case 209: - break; - case 47: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); - } - case 210: - break; - case 48: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); - } - case 211: - break; - case 49: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DESCENDANTS, yytext()); - } - case 212: - break; - case 50: { - return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, yytext()); - } - case 213: - break; - case 51: { - return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); - } - case 214: - break; - case 52: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FILTER, yytext()); - } - case 215: - break; - case 53: { - yybegin(XMLOPENTAG); - string.setLength(0); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext()); - } - case 216: - break; - case 54: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); - } - case 217: - break; - case 55: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); - } - case 218: - break; - case 56: { - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext()); - } - case 219: - break; - case 57: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); - } - case 220: - break; - case 58: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); - } - case 221: - break; - case 59: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); - } - case 222: - break; - case 60: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); - } - case 223: - break; - case 61: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); - } - case 224: - break; - case 62: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); - } - case 225: - break; - case 63: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); - } - case 226: - break; - case 64: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); - } - case 227: - break; - case 65: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); - } - case 228: - break; - case 66: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); - } - case 229: - break; - case 67: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); - } - case 230: - break; - case 68: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IF, yytext()); - } - case 231: - break; - case 69: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); - } - case 232: - break; - case 70: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IN, yytext()); - } - case 233: - break; - case 71: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DO, yytext()); - } - case 234: - break; - case 72: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); - } - case 235: - break; - case 73: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); - } - case 236: - break; - case 74: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); - } - case 237: - break; - case 75: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); - } - case 238: - break; - case 76: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); - } - case 239: - break; - case 77: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); - } - case 240: - break; - case 78: { /* ignore illegal character escape */ - - } - case 241: - break; - case 79: { - string.append('\"'); - } - case 242: - break; - case 80: { - string.append('\''); - } - case 243: - break; - case 81: { - string.append('\f'); - } - case 244: - break; - case 82: { - string.append('\\'); - } - case 245: - break; - case 83: { - string.append('\b'); - } - case 246: - break; - case 84: { - string.append('\r'); - } - case 247: - break; - case 85: { - string.append('\n'); - } - case 248: - break; - case 86: { - string.append('\t'); - } - case 249: - break; - case 87: { - yybegin(XML); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTFINISHTAG_END, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 250: - break; - case 88: { - yybegin(XMLOPENTAGATTRIB); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTENAME, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 251: - break; - case 89: { - yybegin(XMLOPENTAG); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); - } - case 252: - break; - case 90: { - yybegin(XMLINSTRATTRIB); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTENAME, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 253: - break; - case 91: { - yybegin(XML); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTR_END, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 254: - break; - case 92: { - yybegin(XMLINSTROPENTAG); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); - } - case 255: - break; - case 93: { - yybegin(XMLOPENTAG); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 256: - break; - case 94: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 257: - break; - case 95: { - throw new AVM2ParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); - } - case 258: - break; - case 96: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); - } - case 259: - break; - case 97: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); - } - case 260: - break; - case 98: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); - } - case 261: - break; - case 99: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); - } - case 262: - break; - case 100: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); - } - case 263: - break; - case 101: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); - } - case 264: - break; - case 102: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); - } - case 265: - break; - case 103: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FOR, yytext()); - } - case 266: - break; - case 104: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.SET, yytext()); - } - case 267: - break; - case 105: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); - } - case 268: - break; - case 106: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRY, yytext()); - } - case 269: - break; - case 107: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.USE, yytext()); - } - case 270: - break; - case 108: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.VAR, yytext()); - } - case 271: - break; - case 109: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.GET, yytext()); - } - case 272: - break; - case 110: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); - } - case 273: - break; - case 111: { - string.append(yytext()); - yybegin(XML); - String ret = string.toString(); - string.setLength(0); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_CDATA, ret); - } - case 274: - break; - case 112: { - string.append(yytext()); - yybegin(XML); - String ret = string.toString(); - string.setLength(0); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_COMMENT, ret); - } - case 275: - break; - case 113: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHVARTAG_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 276: - break; - case 114: { - yybegin(XMLINSTROPENTAG); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTR_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 277: - break; - case 115: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRVARTAG_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 278: - break; - case 116: { - string.append('\u00A7'); - } - case 279: - break; - case 117: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); - } - case 280: - break; - case 118: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.EACH, yytext()); - } - case 281: - break; - case 119: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.ELSE, yytext()); - } - case 282: - break; - case 120: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CASE, yytext()); - } - case 283: - break; - case 121: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); - } - case 284: - break; - case 122: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); - } - case 285: - break; - case 123: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); - } - case 286: - break; - case 124: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WITH, yytext()); - } - case 287: - break; - case 125: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); - } - case 288: - break; - case 126: { - char val = (char) Integer.parseInt(yytext().substring(2), 16); - string.append(val); - } - case 289: - break; - case 127: { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHTAG, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 290: - break; - case 128: { - String ret = string.toString(); - string.setLength(0); - string.append(yytext()); - yybegin(XMLCOMMENT); - if (!ret.isEmpty()) { - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, ret); - } - } - case 291: - break; - case 129: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); - } - case 292: - break; - case 130: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.FINAL, yytext()); - } - case 293: - break; - case 131: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.BREAK, yytext()); - } - case 294: - break; - case 132: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CATCH, yytext()); - } - case 295: - break; - case 133: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONST, yytext()); - } - case 296: - break; - case 134: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CLASS, yytext()); - } - case 297: - break; - case 135: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SUPER, yytext()); - } - case 298: - break; - case 136: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THROW, yytext()); - } - case 299: - break; - case 137: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WHILE, yytext()); - } - case 300: - break; - case 138: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.RETURN, yytext()); - } - case 301: - break; - case 139: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.STATIC, yytext()); - } - case 302: - break; - case 140: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SWITCH, yytext()); - } - case 303: - break; - case 141: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.NATIVE, yytext()); - } - case 304: - break; - case 142: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); - } - case 305: - break; - case 143: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPORT, yytext()); - } - case 306: - break; - case 144: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); - } - case 307: - break; - case 145: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PUBLIC, yytext()); - } - case 308: - break; - case 146: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FINALLY, yytext()); - } - case 309: - break; - case 147: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EXTENDS, yytext()); - } - case 310: - break; - case 148: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DEFAULT, yytext()); - } - case 311: - break; - case 149: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.DYNAMIC, yytext()); - } - case 312: - break; - case 150: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PRIVATE, yytext()); - } - case 313: - break; - case 151: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PACKAGE, yytext()); - } - case 314: - break; - case 152: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FUNCTION, yytext()); - } - case 315: - break; - case 153: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONTINUE, yytext()); - } - case 316: - break; - case 154: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.OVERRIDE, yytext()); - } - case 317: - break; - case 155: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERNAL, yytext()); - } - case 318: - break; - case 156: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); - } - case 319: - break; - case 157: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE, yytext()); - } - case 320: - break; - case 158: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERFACE, yytext()); - } - case 321: - break; - case 159: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); - } - case 322: - break; - case 160: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PROTECTED, yytext()); - } - case 323: - break; - case 161: { - String ret = string.toString(); - string.setLength(0); - string.append(yytext()); - yybegin(XMLCDATA); - if (!ret.isEmpty()) { - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, ret); - } - } - case 324: - break; - case 162: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); - } - case 325: - break; - case 163: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPLEMENTS, yytext()); - } - case 326: - break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - { - return new ParsedSymbol(SymbolGroup.EOF, SymbolType.EOF, null); - } - } else { - zzScanError(ZZ_NO_MATCH); - } - } - } - } -} +/* The following code was generated by JFlex 1.6.0 */ + +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + +/** + * This class is a scanner generated by + * JFlex 1.6.0 + * from the specification file C:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript3_script.flex + */ +public final class ActionScriptLexer { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + public static final int STRING = 2; + public static final int CHARLITERAL = 4; + public static final int XMLOPENTAG = 6; + public static final int XMLOPENTAGATTRIB = 8; + public static final int XMLINSTROPENTAG = 10; + public static final int XMLINSTRATTRIB = 12; + public static final int XMLCDATA = 14; + public static final int XMLCOMMENT = 16; + public static final int XML = 18; + public static final int OIDENTIFIER = 20; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, + 8, 8, 9, 9, 10, 10 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\13\1\2\1\113\1\3\1\1\22\0\1\13\1\14\1\33"+ + "\1\0\1\6\1\110\1\105\1\34\1\76\1\77\1\5\1\45\1\103"+ + "\1\15\1\11\1\4\1\35\3\41\4\42\2\21\1\17\1\102\1\12"+ + "\1\32\1\16\1\23\1\111\1\27\1\20\1\25\1\26\1\43\1\20"+ + "\2\10\1\74\4\10\1\75\5\10\1\30\3\10\1\37\2\10\1\24"+ + "\1\46\1\31\1\107\1\10\1\0\1\52\1\50\1\54\1\63\1\44"+ + "\1\40\1\73\1\66\1\61\1\10\1\53\1\64\1\71\1\57\1\56"+ + "\1\67\1\10\1\51\1\55\1\60\1\62\1\72\1\65\1\36\1\70"+ + "\1\10\1\100\1\106\1\101\1\104\6\0\1\113\41\0\1\47\2\0"+ + "\1\6\12\0\1\6\1\0\1\22\2\0\1\6\5\0\2\6\1\112"+ + "\24\6\1\0\37\6\1\0\u01ca\6\4\0\14\6\16\0\5\6\7\0"+ + "\1\6\1\0\1\6\21\0\160\7\5\6\1\0\2\6\2\0\4\6"+ + "\1\0\1\6\6\0\1\6\1\0\3\6\1\0\1\6\1\0\24\6"+ + "\1\0\123\6\1\0\213\6\1\0\5\7\2\0\246\6\1\0\46\6"+ + "\2\0\1\6\7\0\47\6\11\0\55\7\1\0\1\7\1\0\2\7"+ + "\1\0\2\7\1\0\1\7\10\0\33\6\5\0\3\6\35\0\13\7"+ + "\5\0\53\6\37\7\4\0\2\6\1\7\143\6\1\0\1\6\7\7"+ + "\2\0\6\7\2\6\2\7\1\0\4\7\2\6\12\7\3\6\2\0"+ + "\1\6\20\0\1\6\1\7\36\6\33\7\2\0\131\6\13\7\1\6"+ + "\16\0\12\7\41\6\11\7\2\6\4\0\1\6\5\0\26\6\4\7"+ + "\1\6\11\7\1\6\3\7\1\6\5\7\22\0\31\6\3\7\104\0"+ + "\23\6\61\0\40\7\66\6\3\7\1\6\22\7\1\6\7\7\12\6"+ + "\2\7\2\0\12\7\1\0\20\6\3\7\1\0\10\6\2\0\2\6"+ + "\2\0\26\6\1\0\7\6\1\0\1\6\3\0\4\6\2\0\1\7"+ + "\1\6\7\7\2\0\2\7\2\0\3\7\1\6\10\0\1\7\4\0"+ + "\2\6\1\0\3\6\2\7\2\0\12\7\2\6\17\0\3\7\1\0"+ + "\6\6\4\0\2\6\2\0\26\6\1\0\7\6\1\0\2\6\1\0"+ + "\2\6\1\0\2\6\2\0\1\7\1\0\5\7\4\0\2\7\2\0"+ + "\3\7\3\0\1\7\7\0\4\6\1\0\1\6\7\0\14\7\3\6"+ + "\1\7\13\0\3\7\1\0\11\6\1\0\3\6\1\0\26\6\1\0"+ + "\7\6\1\0\2\6\1\0\5\6\2\0\1\7\1\6\10\7\1\0"+ + "\3\7\1\0\3\7\2\0\1\6\17\0\2\6\2\7\2\0\12\7"+ + "\21\0\3\7\1\0\10\6\2\0\2\6\2\0\26\6\1\0\7\6"+ + "\1\0\2\6\1\0\5\6\2\0\1\7\1\6\7\7\2\0\2\7"+ + "\2\0\3\7\10\0\2\7\4\0\2\6\1\0\3\6\2\7\2\0"+ + "\12\7\1\0\1\6\20\0\1\7\1\6\1\0\6\6\3\0\3\6"+ + "\1\0\4\6\3\0\2\6\1\0\1\6\1\0\2\6\3\0\2\6"+ + "\3\0\3\6\3\0\14\6\4\0\5\7\3\0\3\7\1\0\4\7"+ + "\2\0\1\6\6\0\1\7\16\0\12\7\20\0\4\7\1\0\10\6"+ + "\1\0\3\6\1\0\27\6\1\0\20\6\3\0\1\6\7\7\1\0"+ + "\3\7\1\0\4\7\7\0\2\7\1\0\2\6\6\0\2\6\2\7"+ + "\2\0\12\7\21\0\3\7\1\0\10\6\1\0\3\6\1\0\27\6"+ + "\1\0\12\6\1\0\5\6\2\0\1\7\1\6\7\7\1\0\3\7"+ + "\1\0\4\7\7\0\2\7\7\0\1\6\1\0\2\6\2\7\2\0"+ + "\12\7\1\0\2\6\16\0\3\7\1\0\10\6\1\0\3\6\1\0"+ + "\51\6\2\0\1\6\7\7\1\0\3\7\1\0\4\7\1\6\10\0"+ + "\1\7\10\0\2\6\2\7\2\0\12\7\12\0\6\6\2\0\2\7"+ + "\1\0\22\6\3\0\30\6\1\0\11\6\1\0\1\6\2\0\7\6"+ + "\3\0\1\7\4\0\6\7\1\0\1\7\1\0\10\7\6\0\12\7"+ + "\2\0\2\7\15\0\60\6\1\7\2\6\7\7\5\0\7\6\10\7"+ + "\1\0\12\7\47\0\2\6\1\0\1\6\2\0\2\6\1\0\1\6"+ + "\2\0\1\6\6\0\4\6\1\0\7\6\1\0\3\6\1\0\1\6"+ + "\1\0\1\6\2\0\2\6\1\0\4\6\1\7\2\6\6\7\1\0"+ + "\2\7\1\6\2\0\5\6\1\0\1\6\1\0\6\7\2\0\12\7"+ + "\2\0\4\6\40\0\1\6\27\0\2\7\6\0\12\7\13\0\1\7"+ + "\1\0\1\7\1\0\1\7\4\0\2\7\10\6\1\0\44\6\4\0"+ + "\24\7\1\0\2\7\5\6\13\7\1\0\44\7\11\0\1\7\71\0"+ + "\53\6\24\7\1\6\12\7\6\0\6\6\4\7\4\6\3\7\1\6"+ + "\3\7\2\6\7\7\3\6\4\7\15\6\14\7\1\6\17\7\2\0"+ + "\46\6\1\0\1\6\5\0\1\6\2\0\53\6\1\0\u014d\6\1\0"+ + "\4\6\2\0\7\6\1\0\1\6\1\0\4\6\2\0\51\6\1\0"+ + "\4\6\2\0\41\6\1\0\4\6\2\0\7\6\1\0\1\6\1\0"+ + "\4\6\2\0\17\6\1\0\71\6\1\0\4\6\2\0\103\6\2\0"+ + "\3\7\40\0\20\6\20\0\125\6\14\0\u026c\6\2\0\21\6\1\0"+ + "\32\6\5\0\113\6\3\0\3\7\10\6\7\0\15\6\1\0\4\6"+ + "\3\7\13\0\22\6\3\7\13\0\22\6\2\7\14\0\15\6\1\0"+ + "\3\6\1\0\2\7\14\0\64\6\40\7\3\0\1\6\4\0\1\6"+ + "\1\7\2\0\12\7\41\0\3\7\2\0\12\7\6\0\130\6\10\0"+ + "\51\6\1\7\1\6\5\0\106\6\12\0\37\6\1\0\14\7\4\0"+ + "\14\7\12\0\12\7\36\6\2\0\5\6\13\0\54\6\4\0\21\7"+ + "\7\6\2\7\6\0\12\7\46\0\27\6\5\7\4\0\65\6\12\7"+ + "\1\0\35\7\2\0\13\7\6\0\12\7\15\0\1\6\10\0\16\7"+ + "\102\0\5\7\57\6\21\7\7\6\4\0\12\7\21\0\11\7\14\0"+ + "\3\7\36\6\15\7\2\6\12\7\54\6\16\7\14\0\44\6\24\7"+ + "\10\0\12\7\3\0\3\6\12\7\44\6\122\0\3\7\1\0\25\7"+ + "\4\6\1\7\4\6\3\7\2\6\1\0\2\7\6\0\300\6\66\7"+ + "\6\0\4\7\u0116\6\2\0\6\6\2\0\46\6\2\0\6\6\2\0"+ + "\10\6\1\0\1\6\1\0\1\6\1\0\1\6\1\0\37\6\2\0"+ + "\65\6\1\0\7\6\1\0\1\6\3\0\3\6\1\0\7\6\3\0"+ + "\4\6\2\0\6\6\4\0\15\6\5\0\3\6\1\0\7\6\3\0"+ + "\14\0\2\0\32\0\1\113\1\113\25\0\2\7\23\0\1\7\33\0"+ + "\1\0\1\6\15\0\1\6\20\0\15\6\63\0\15\7\4\0\1\7"+ + "\3\0\14\7\21\0\1\6\4\0\1\6\2\0\12\6\1\0\1\6"+ + "\3\0\5\6\6\0\1\6\1\0\1\6\1\0\1\6\1\0\4\6"+ + "\1\0\13\6\2\0\4\6\5\0\5\6\4\0\1\6\21\0\43\7"+ + "\2\6\4\7\7\0\u0a70\0\57\6\1\0\57\6\1\0\205\6\6\0"+ + "\4\6\3\7\2\6\14\0\46\6\1\0\1\6\5\0\1\6\2\0"+ + "\70\6\7\0\1\6\17\0\1\7\27\6\11\0\7\6\1\0\7\6"+ + "\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6"+ + "\1\0\7\6\1\0\40\7\57\0\1\6\u01c0\0\21\0\4\0\2\6"+ + "\1\7\31\0\17\7\1\0\5\6\2\0\3\7\2\6\4\0\126\6"+ + "\2\0\2\7\2\0\3\6\1\0\132\6\1\0\4\6\5\0\51\6"+ + "\3\0\136\6\21\0\33\6\65\0\20\6\u0200\0\u19b6\6\112\0\u51cd\6"+ + "\63\0\u048d\6\103\0\56\6\2\0\u010d\6\3\0\20\6\12\7\2\6"+ + "\24\0\57\6\1\7\4\0\12\7\1\0\37\6\1\0\1\7\106\6"+ + "\14\7\45\0\11\6\2\0\147\6\2\0\4\6\1\0\36\6\2\0"+ + "\2\6\105\0\13\6\1\7\3\6\1\7\4\6\1\7\27\6\5\7"+ + "\30\0\64\6\14\0\2\7\62\6\21\7\13\0\12\7\6\0\22\7"+ + "\6\6\3\0\1\6\4\0\12\7\34\6\10\7\2\0\27\6\15\7"+ + "\14\0\35\6\3\0\4\7\57\6\16\7\16\0\1\6\12\7\6\0"+ + "\5\6\1\7\12\6\12\7\5\6\1\0\51\6\16\7\11\0\3\6"+ + "\1\7\10\6\2\7\2\0\12\7\6\0\27\6\3\0\1\6\3\7"+ + "\62\6\1\7\1\6\3\7\2\6\2\7\5\6\2\7\1\6\1\7"+ + "\1\6\30\0\3\6\2\0\13\6\5\7\2\0\3\6\2\7\12\0"+ + "\6\6\2\0\6\6\2\0\6\6\11\0\7\6\1\0\7\6\1\0"+ + "\53\6\1\0\4\6\4\0\2\6\132\0\43\6\10\7\1\0\2\7"+ + "\2\0\12\7\6\0\u2ba4\6\14\0\27\6\4\0\61\6\4\0\u1800\0"+ + "\u0900\0\u016e\6\2\0\152\6\46\0\7\6\14\0\5\6\5\0\1\6"+ + "\1\7\12\6\1\0\15\6\1\0\5\6\1\0\1\6\1\0\2\6"+ + "\1\0\2\6\1\0\154\6\41\0\u016b\6\22\0\100\6\2\0\66\6"+ + "\10\0\40\0\14\6\4\0\20\7\20\0\16\7\5\0\2\7\30\0"+ + "\3\7\40\0\5\6\1\0\207\6\23\0\12\7\7\0\32\6\4\0"+ + "\1\7\1\0\32\6\13\0\131\6\3\0\6\6\2\0\6\6\2\0"+ + "\6\6\2\0\3\6\41\0\2\0\14\6\1\0\32\6\1\0\23\6"+ + "\1\0\2\6\1\0\17\6\2\0\16\6\42\0\173\6\105\0\65\7"+ + "\210\0\1\7\202\0\35\6\3\0\61\6\17\0\1\7\37\0\40\6"+ + "\20\0\21\6\1\7\10\6\1\7\5\0\46\6\5\7\5\0\36\6"+ + "\2\0\44\6\4\0\10\6\1\0\5\7\52\0\236\6\2\0\12\7"+ + "\126\0\50\6\10\0\64\6\234\0\u0137\6\11\0\26\6\12\0\10\6"+ + "\230\0\6\6\2\0\1\6\1\0\54\6\1\0\2\6\3\0\1\6"+ + "\2\0\27\6\12\0\27\6\11\0\37\6\141\0\26\6\12\0\32\6"+ + "\106\0\70\6\6\0\2\6\100\0\1\6\3\7\1\0\2\7\5\0"+ + "\4\7\4\6\1\0\3\6\1\0\33\6\4\0\3\7\4\0\1\7"+ + "\40\0\35\6\3\0\35\6\43\0\10\6\1\0\34\6\2\7\31\0"+ + "\66\6\12\0\26\6\12\0\23\6\15\0\22\6\156\0\111\6\u03b7\0"+ + "\3\7\65\6\17\7\37\0\12\7\17\0\4\7\55\6\13\7\25\0"+ + "\31\6\7\0\12\7\6\0\3\7\44\6\16\7\1\0\12\7\20\0"+ + "\43\6\1\7\2\0\1\6\11\0\3\7\60\6\16\7\4\6\13\0"+ + "\12\7\1\6\45\0\22\6\1\0\31\6\14\7\170\0\57\6\14\7"+ + "\5\0\12\7\7\0\3\7\1\0\10\6\2\0\2\6\2\0\26\6"+ + "\1\0\7\6\1\0\2\6\1\0\5\6\2\0\1\7\1\6\7\7"+ + "\2\0\2\7\2\0\3\7\11\0\1\7\5\0\5\6\2\7\2\0"+ + "\7\7\3\0\5\7\u010b\0\60\6\24\7\2\6\1\0\1\6\10\0"+ + "\12\7\246\0\57\6\7\7\2\0\11\7\77\0\60\6\21\7\3\0"+ + "\1\6\13\0\12\7\46\0\53\6\15\7\10\0\12\7\u01d6\0\100\6"+ + "\12\7\25\0\1\6\u01c0\0\71\6\u0507\0\u0399\6\147\0\157\7\u0b91\0"+ + "\u042f\6\u33d1\0\u0239\6\7\0\37\6\1\0\12\7\146\0\36\6\2\0"+ + "\5\7\13\0\60\6\7\7\11\0\4\6\14\0\12\7\11\0\25\6"+ + "\5\0\23\6\u0370\0\105\6\13\0\1\6\56\7\20\0\4\7\15\6"+ + "\u4060\0\2\6\u0bfe\0\153\6\5\0\15\6\3\0\11\6\7\0\12\6"+ + "\3\0\2\7\u14c6\0\5\7\3\0\6\7\10\0\10\7\2\0\7\7"+ + "\36\0\4\7\224\0\3\7\u01bb\0\125\6\1\0\107\6\1\0\2\6"+ + "\2\0\1\6\2\0\2\6\2\0\4\6\1\0\14\6\1\0\1\6"+ + "\1\0\7\6\1\0\101\6\1\0\4\6\2\0\10\6\1\0\7\6"+ + "\1\0\34\6\1\0\4\6\1\0\5\6\1\0\1\6\3\0\7\6"+ + "\1\0\u0154\6\2\0\31\6\1\0\31\6\1\0\37\6\1\0\31\6"+ + "\1\0\37\6\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6"+ + "\1\0\31\6\1\0\10\6\2\0\62\7\u1000\0\305\6\13\0\7\7"+ + "\u0529\0\4\6\1\0\33\6\1\0\2\6\1\0\1\6\2\0\1\6"+ + "\1\0\12\6\1\0\4\6\1\0\1\6\1\0\1\6\6\0\1\6"+ + "\4\0\1\6\1\0\1\6\1\0\1\6\1\0\3\6\1\0\2\6"+ + "\1\0\1\6\2\0\1\6\1\0\1\6\1\0\1\6\1\0\1\6"+ + "\1\0\1\6\1\0\2\6\1\0\1\6\2\0\4\6\1\0\7\6"+ + "\1\0\4\6\1\0\4\6\1\0\1\6\1\0\12\6\1\0\21\6"+ + "\5\0\3\6\1\0\5\6\1\0\21\6\u1144\0\ua6d7\6\51\0\u1035\6"+ + "\13\0\336\6\u3fe2\0\u021e\6\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\u06ed\0"+ + "\360\7\uffff\0\uffff\0\ufe12\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\13\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7"+ + "\1\10\1\11\1\12\1\13\1\14\1\15\1\16\1\17"+ + "\1\20\1\21\1\22\1\23\1\15\2\6\1\24\1\25"+ + "\21\6\1\26\1\27\1\30\1\31\1\32\1\33\1\34"+ + "\1\35\1\36\1\37\1\40\1\41\1\42\2\43\1\44"+ + "\1\1\1\42\2\45\2\46\1\42\2\1\1\47\1\50"+ + "\1\1\1\51\2\1\1\52\1\1\1\53\2\42\2\54"+ + "\2\42\1\55\1\42\1\1\1\56\1\3\1\0\1\57"+ + "\1\60\1\61\1\62\1\63\1\64\1\65\1\66\1\67"+ + "\1\70\1\71\1\72\1\73\1\74\1\75\1\76\1\0"+ + "\1\77\1\63\1\100\1\0\2\100\7\6\1\101\1\102"+ + "\1\0\2\6\1\103\16\6\1\104\1\105\1\106\4\6"+ + "\1\107\13\6\1\110\1\111\1\112\1\113\1\114\1\115"+ + "\1\116\1\117\1\120\1\116\1\121\1\122\1\123\1\124"+ + "\1\125\1\126\1\116\1\127\1\0\1\130\1\0\1\131"+ + "\1\0\1\132\1\133\1\0\1\134\4\0\1\135\2\0"+ + "\1\136\4\137\2\3\2\0\1\140\1\141\1\142\1\143"+ + "\1\144\1\0\1\63\1\145\2\146\1\100\1\6\1\147"+ + "\5\6\1\150\6\6\1\151\4\6\1\152\4\6\1\153"+ + "\6\6\1\154\12\6\1\155\1\6\1\156\1\6\1\157"+ + "\3\0\1\134\1\160\1\161\1\0\1\162\2\0\1\163"+ + "\1\164\1\165\1\0\1\166\1\146\1\100\4\6\1\167"+ + "\1\170\2\6\1\171\12\6\1\172\1\173\1\6\1\174"+ + "\11\6\1\175\5\6\1\176\1\6\1\177\2\0\1\200"+ + "\1\201\1\0\1\146\1\100\1\202\1\203\2\6\1\204"+ + "\1\6\1\205\1\206\1\6\1\207\1\6\1\210\4\6"+ + "\1\211\11\6\1\212\5\6\1\0\1\146\1\100\3\6"+ + "\1\213\1\6\1\214\1\215\1\6\1\216\1\6\1\217"+ + "\3\6\1\220\3\6\1\221\4\6\1\222\1\6\1\0"+ + "\1\146\1\100\1\223\1\6\1\224\10\6\1\225\1\226"+ + "\1\6\1\227\1\230\1\6\1\0\1\146\1\100\1\231"+ + "\1\232\1\233\3\6\1\234\3\6\1\235\1\0\1\146"+ + "\1\100\1\236\1\6\1\237\1\6\1\240\1\241\1\242"+ + "\1\146\1\100\1\243\1\244\6\100"; + + private static int [] zzUnpackAction() { + int [] result = new int[448]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\114\0\230\0\344\0\u0130\0\u017c\0\u01c8\0\u0214"+ + "\0\u0260\0\u02ac\0\u02f8\0\u0344\0\u0390\0\u0344\0\u03dc\0\u0428"+ + "\0\u0474\0\u04c0\0\u050c\0\u0558\0\u05a4\0\u05f0\0\u063c\0\u0688"+ + "\0\u06d4\0\u0344\0\u0344\0\u0344\0\u0720\0\u0344\0\u0344\0\u076c"+ + "\0\u07b8\0\u0804\0\u0850\0\u089c\0\u08e8\0\u0934\0\u0980\0\u09cc"+ + "\0\u0a18\0\u0a64\0\u0ab0\0\u0afc\0\u0b48\0\u0b94\0\u0be0\0\u0c2c"+ + "\0\u0c78\0\u0cc4\0\u0d10\0\u0d5c\0\u0da8\0\u0344\0\u0344\0\u0344"+ + "\0\u0344\0\u0344\0\u0344\0\u0344\0\u0df4\0\u0e40\0\u0e8c\0\u0ed8"+ + "\0\u0344\0\u0f24\0\u0f70\0\u0344\0\u0344\0\u0fbc\0\u1008\0\u1054"+ + "\0\u0344\0\u10a0\0\u0344\0\u10ec\0\u1138\0\u1184\0\u0344\0\u0344"+ + "\0\u11d0\0\u0344\0\u121c\0\u1268\0\u0344\0\u12b4\0\u0344\0\u0344"+ + "\0\u1300\0\u134c\0\u0344\0\u1398\0\u13e4\0\u0344\0\u1430\0\u147c"+ + "\0\u0344\0\u14c8\0\u1514\0\u0344\0\u0344\0\u1560\0\u0344\0\u15ac"+ + "\0\u0344\0\u15f8\0\u1644\0\u0344\0\u0344\0\u1690\0\u0344\0\u0344"+ + "\0\u16dc\0\u0344\0\u0344\0\u1728\0\u1774\0\u17c0\0\u180c\0\u1858"+ + "\0\u18a4\0\u18f0\0\u193c\0\u1988\0\u19d4\0\u1a20\0\u1a6c\0\u1ab8"+ + "\0\u1b04\0\u0344\0\u0344\0\u1b50\0\u1b9c\0\u1be8\0\u04c0\0\u1c34"+ + "\0\u1c80\0\u1ccc\0\u1d18\0\u1d64\0\u1db0\0\u1dfc\0\u1e48\0\u1e94"+ + "\0\u1ee0\0\u1f2c\0\u1f78\0\u1fc4\0\u2010\0\u04c0\0\u04c0\0\u205c"+ + "\0\u20a8\0\u20f4\0\u2140\0\u218c\0\u04c0\0\u21d8\0\u2224\0\u2270"+ + "\0\u22bc\0\u2308\0\u2354\0\u23a0\0\u23ec\0\u2438\0\u2484\0\u24d0"+ + "\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344"+ + "\0\u0344\0\u251c\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344"+ + "\0\u2568\0\u0344\0\u1184\0\u0344\0\u11d0\0\u0344\0\u121c\0\u0344"+ + "\0\u0344\0\u12b4\0\u25b4\0\u2600\0\u264c\0\u2698\0\u26e4\0\u2730"+ + "\0\u277c\0\u27c8\0\u0344\0\u0344\0\u251c\0\u2568\0\u2814\0\u2860"+ + "\0\u0344\0\u28ac\0\u28f8\0\u0344\0\u0344\0\u0344\0\u2944\0\u0344"+ + "\0\u2990\0\u2990\0\u0344\0\u29dc\0\u1858\0\u2a28\0\u2a74\0\u04c0"+ + "\0\u2ac0\0\u2b0c\0\u2b58\0\u2ba4\0\u2bf0\0\u2c3c\0\u2c88\0\u2cd4"+ + "\0\u2d20\0\u2d6c\0\u2db8\0\u2e04\0\u04c0\0\u2e50\0\u2e9c\0\u2ee8"+ + "\0\u2f34\0\u04c0\0\u2f80\0\u2fcc\0\u3018\0\u3064\0\u04c0\0\u30b0"+ + "\0\u30fc\0\u3148\0\u3194\0\u31e0\0\u322c\0\u04c0\0\u3278\0\u32c4"+ + "\0\u3310\0\u335c\0\u33a8\0\u33f4\0\u3440\0\u348c\0\u34d8\0\u3524"+ + "\0\u04c0\0\u3570\0\u04c0\0\u35bc\0\u04c0\0\u3608\0\u3654\0\u25b4"+ + "\0\u0344\0\u0344\0\u0344\0\u36a0\0\u0344\0\u36ec\0\u3738\0\u3784"+ + "\0\u0344\0\u0344\0\u37d0\0\u0344\0\u381c\0\u3868\0\u38b4\0\u3900"+ + "\0\u394c\0\u3998\0\u04c0\0\u04c0\0\u39e4\0\u3a30\0\u04c0\0\u3a7c"+ + "\0\u3ac8\0\u3b14\0\u3b60\0\u3bac\0\u3bf8\0\u3c44\0\u3c90\0\u3cdc"+ + "\0\u3d28\0\u04c0\0\u04c0\0\u3d74\0\u04c0\0\u3dc0\0\u3e0c\0\u3e58"+ + "\0\u3ea4\0\u3ef0\0\u3f3c\0\u3f88\0\u3fd4\0\u4020\0\u04c0\0\u406c"+ + "\0\u40b8\0\u4104\0\u4150\0\u419c\0\u04c0\0\u41e8\0\u0344\0\u251c"+ + "\0\u4234\0\u0344\0\u0344\0\u4280\0\u42cc\0\u4318\0\u04c0\0\u4364"+ + "\0\u43b0\0\u43fc\0\u04c0\0\u4448\0\u04c0\0\u04c0\0\u4494\0\u04c0"+ + "\0\u44e0\0\u04c0\0\u452c\0\u4578\0\u45c4\0\u4610\0\u04c0\0\u465c"+ + "\0\u46a8\0\u46f4\0\u4740\0\u478c\0\u47d8\0\u4824\0\u4870\0\u48bc"+ + "\0\u04c0\0\u4908\0\u4954\0\u49a0\0\u49ec\0\u4a38\0\u4a84\0\u4ad0"+ + "\0\u4b1c\0\u4b68\0\u4bb4\0\u4c00\0\u04c0\0\u4c4c\0\u04c0\0\u04c0"+ + "\0\u4c98\0\u04c0\0\u4ce4\0\u04c0\0\u4d30\0\u4d7c\0\u4dc8\0\u04c0"+ + "\0\u4e14\0\u4e60\0\u4eac\0\u04c0\0\u4ef8\0\u4f44\0\u4f90\0\u4fdc"+ + "\0\u04c0\0\u5028\0\u5074\0\u50c0\0\u510c\0\u04c0\0\u5158\0\u04c0"+ + "\0\u51a4\0\u51f0\0\u523c\0\u5288\0\u52d4\0\u5320\0\u536c\0\u53b8"+ + "\0\u04c0\0\u04c0\0\u5404\0\u04c0\0\u04c0\0\u5450\0\u549c\0\u54e8"+ + "\0\u5534\0\u04c0\0\u04c0\0\u04c0\0\u5580\0\u55cc\0\u5618\0\u04c0"+ + "\0\u5664\0\u56b0\0\u56fc\0\u04c0\0\u5748\0\u5794\0\u57e0\0\u04c0"+ + "\0\u582c\0\u04c0\0\u5878\0\u04c0\0\u04c0\0\u0344\0\u0344\0\u58c4"+ + "\0\u04c0\0\u04c0\0\u5910\0\u595c\0\u59a8\0\u59f4\0\u5a40\0\u17c0"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[448]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\14\1\15\1\16\1\17\1\20\1\21\1\22\1\14"+ + "\1\22\1\23\1\24\1\17\1\25\1\26\1\27\1\30"+ + "\1\22\1\31\1\14\1\32\1\33\4\22\1\34\1\35"+ + "\1\36\1\37\1\40\2\22\1\41\2\31\1\22\1\42"+ + "\1\43\1\14\1\44\1\45\1\46\1\47\1\22\1\50"+ + "\1\51\1\52\1\53\1\54\1\55\1\56\1\57\1\22"+ + "\1\60\1\22\1\61\2\22\1\62\1\63\1\64\1\65"+ + "\1\66\1\67\1\70\1\71\1\72\1\73\1\74\1\75"+ + "\1\76\1\77\1\100\1\101\1\22\1\14\1\102\1\103"+ + "\1\104\30\102\1\105\12\102\1\106\45\102\1\107\1\110"+ + "\1\111\31\107\1\105\11\107\1\106\45\107\1\14\1\112"+ + "\1\113\1\114\1\115\3\14\1\116\2\14\1\114\2\14"+ + "\1\117\2\116\4\14\4\116\5\14\3\116\2\14\2\116"+ + "\3\14\26\116\2\14\1\120\46\14\1\121\44\14\1\122"+ + "\14\14\1\112\1\113\1\114\4\14\1\123\2\14\1\114"+ + "\3\14\2\123\2\14\1\124\1\14\4\123\5\14\3\123"+ + "\2\14\2\123\3\14\26\123\2\14\1\125\46\14\1\126"+ + "\44\14\1\127\13\14\1\130\1\112\1\113\26\130\1\131"+ + "\63\130\1\132\1\133\12\130\1\134\77\130\1\112\1\113"+ + "\7\130\1\135\65\130\1\136\13\130\1\137\1\110\1\111"+ + "\43\137\1\140\1\141\44\137\116\0\1\16\114\0\1\17"+ + "\7\0\1\17\104\0\1\142\1\143\24\0\1\144\113\0"+ + "\1\145\67\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\26\22\14\0\1\22\12\0\1\146\1\147"+ + "\6\0\1\150\13\0\1\150\3\0\2\150\33\0\1\151"+ + "\25\0\1\152\1\0\1\153\4\0\2\152\4\0\4\152"+ + "\1\0\1\154\3\0\3\152\2\0\2\152\3\0\26\152"+ + "\2\0\1\155\45\0\1\156\76\0\1\157\14\0\1\160"+ + "\77\0\1\161\13\0\1\162\100\0\1\163\105\0\1\150"+ + "\7\0\1\31\13\0\1\31\3\0\2\31\2\164\101\0"+ + "\1\165\72\0\1\150\7\0\1\166\13\0\1\167\2\170"+ + "\1\0\1\171\1\172\2\164\55\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\173\3\22"+ + "\1\174\2\22\1\175\1\176\13\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\1\22\1\177"+ + "\6\22\3\0\2\22\1\200\11\22\1\201\11\22\14\0"+ + "\1\22\33\0\1\202\12\0\1\203\115\0\1\204\52\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\1\22\1\205\24\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\7\22\1\206\3\0\26\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\5\22\1\207\20\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\2\22\1\210\3\22\1\211\5\22\1\212\11\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\213\3\0\10\22\1\214\1\22\1\215"+ + "\2\22\1\216\10\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\22\22\1\217"+ + "\3\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\220\3\0\2\22\1\221\7\22"+ + "\1\222\13\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\1\22\1\223\14\22"+ + "\1\224\1\22\1\225\5\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\3\22\1\226\4\22"+ + "\3\0\5\22\1\227\1\22\1\230\11\22\1\231\4\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\5\22\1\232\1\22\1\233\16\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\234\3\0\6\22\1\235\11\22\1\236"+ + "\5\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\11\22\1\237\4\22\1\240"+ + "\7\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\1\22\1\241\1\242\7\22"+ + "\1\243\13\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\244\3\22"+ + "\1\245\17\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\246\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\7\22\1\247\16\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\2\22\1\250\23\22\14\0\1\22\33\0\1\251\52\0"+ + "\1\252\40\0\1\253\53\0\1\254\37\0\1\255\113\0"+ + "\1\256\61\0\1\102\2\0\30\102\1\0\12\102\1\0"+ + "\45\102\2\0\1\104\111\0\1\257\3\0\27\257\1\260"+ + "\1\261\1\257\1\262\1\257\1\263\5\257\1\264\1\257"+ + "\1\265\1\266\5\257\1\267\1\270\1\257\1\271\30\257"+ + "\1\0\1\107\2\0\31\107\1\0\11\107\1\0\45\107"+ + "\2\0\1\111\113\0\1\113\114\0\1\114\7\0\1\114"+ + "\116\0\1\272\105\0\2\273\3\0\1\273\1\0\4\273"+ + "\2\0\4\273\1\0\1\274\2\0\10\273\3\0\26\273"+ + "\16\0\1\275\2\0\30\275\1\276\60\275\10\0\2\277"+ + "\3\0\1\277\1\0\4\277\2\0\4\277\1\0\1\300"+ + "\2\0\10\277\3\0\26\277\34\0\1\301\75\0\1\302"+ + "\2\0\30\302\1\303\1\304\57\302\31\0\1\305\64\0"+ + "\1\133\126\0\1\306\102\0\1\307\3\0\1\310\3\0"+ + "\1\311\2\0\2\310\2\0\1\312\1\0\4\310\5\0"+ + "\3\310\2\0\2\310\3\0\26\310\2\0\1\313\13\0"+ + "\1\137\2\0\43\137\2\0\44\137\1\314\3\0\32\314"+ + "\1\315\1\314\1\263\5\314\1\264\1\314\1\265\1\266"+ + "\5\314\1\267\1\270\1\314\1\316\27\314\1\317\1\0"+ + "\1\142\1\320\1\321\111\142\5\322\1\323\106\322\11\0"+ + "\1\324\123\0\1\150\13\0\1\150\3\0\2\150\2\164"+ + "\57\0\2\152\3\0\1\152\1\0\4\152\2\0\4\152"+ + "\4\0\10\152\3\0\26\152\50\0\1\325\113\0\1\326"+ + "\77\0\1\327\13\0\1\330\76\0\1\331\3\0\1\332"+ + "\13\0\1\332\3\0\2\332\2\0\1\331\100\0\1\333"+ + "\72\0\1\150\7\0\1\166\13\0\1\166\3\0\2\166"+ + "\2\164\60\0\1\150\7\0\1\166\13\0\1\167\3\0"+ + "\1\171\1\172\2\164\67\0\2\334\3\0\3\334\5\0"+ + "\1\335\2\0\5\334\3\0\1\334\1\0\1\334\1\0"+ + "\1\334\6\0\1\334\41\0\1\150\7\0\1\166\13\0"+ + "\1\172\3\0\2\172\2\164\60\0\1\150\7\0\1\166"+ + "\13\0\1\336\3\0\2\336\2\164\55\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\14\22\1\337"+ + "\11\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\1\22\1\340\24\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\7\22\1\341\16\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\7\22\1\342\16\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\343"+ + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\4\22\1\344\21\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\5\22\1\345\20\22\14\0\1\22\7\0"+ + "\1\346\1\0\1\346\7\0\1\346\4\0\4\346\5\0"+ + "\3\346\2\0\2\346\3\0\26\346\14\0\1\346\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\347"+ + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\10\22\1\350\15\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\5\22\1\351\2\22\1\352\15\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\7\22\1\353\16\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\2\22\1\354\23\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\355\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\356\23\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\17\22\1\357\6\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\11\22\1\360\14\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\7\22\1\361\3\0"+ + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\15\22\1\362\10\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\10\22\1\363\10\22\1\364\4\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\14\22\1\365\11\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\12\22\1\366\5\22\1\367\5\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\1\22\1\370\7\22\1\371\14\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\17\22\1\372\6\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\5\22\1\373"+ + "\2\22\1\374\15\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\17\22\1\375"+ + "\6\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\376\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\13\22\1\377\12\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\3\22\1\u0100\4\22"+ + "\3\0\14\22\1\u0101\11\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\7\22"+ + "\1\u0102\16\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\10\22\1\u0103\15\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\11\22\1\u0104\14\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\6\22\1\u0105\2\22\1\u0106\14\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\4\22\1\u0107\21\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\1\u0108"+ + "\25\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\1\22\1\u0109\24\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\11\22\1\u010a\14\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\10\22\1\u010b\15\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\3\22\1\u010c\4\22\3\0"+ + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\25\22\1\u010d\14\0\1\22"+ + "\21\0\2\u010e\3\0\3\u010e\5\0\1\u010e\2\0\5\u010e"+ + "\3\0\1\u010e\1\0\1\u010e\1\0\1\u010e\6\0\1\u010e"+ + "\50\0\2\u010f\3\0\3\u010f\5\0\1\u010f\2\0\5\u010f"+ + "\3\0\1\u010f\1\0\1\u010f\1\0\1\u010f\6\0\1\u010f"+ + "\30\0\1\u0110\2\0\30\u0110\1\303\1\0\57\u0110\1\304"+ + "\2\0\30\304\1\u0111\60\304\16\0\1\u0112\113\0\1\u0113"+ + "\105\0\1\u0114\6\0\2\u0114\4\0\4\u0114\5\0\3\u0114"+ + "\2\0\2\u0114\3\0\26\u0114\2\0\1\u0115\23\0\2\310"+ + "\3\0\1\310\1\0\4\310\2\0\4\310\4\0\10\310"+ + "\3\0\26\310\33\0\1\u0116\6\0\1\u0117\77\0\1\u0118"+ + "\6\0\2\u0118\4\0\4\u0118\5\0\3\u0118\2\0\2\u0118"+ + "\3\0\26\u0118\2\0\1\u0119\62\0\1\u011a\46\0\1\321"+ + "\111\0\5\322\1\u011b\106\322\4\0\1\321\1\323\140\0"+ + "\1\u011c\102\0\1\332\13\0\1\332\3\0\2\332\71\0"+ + "\2\u011d\3\0\3\u011d\5\0\1\u011d\2\0\5\u011d\3\0"+ + "\1\u011d\1\0\1\u011d\1\0\1\u011d\6\0\1\u011d\41\0"+ + "\1\150\7\0\1\166\13\0\1\u011e\3\0\2\u011e\2\164"+ + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\5\22\1\u011f\20\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22"+ + "\1\u0120\23\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\4\22\1\u0121\21\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\u0122\3\0\26\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\16\22\1\u0123\7\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\7\22\1\u0124\3\0\26\22"+ + "\14\0\1\22\7\0\3\346\7\0\2\346\3\0\4\346"+ + "\4\0\10\346\3\0\26\346\14\0\1\346\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22"+ + "\1\u0125\23\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\12\22\1\u0126\13\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\u0127\3\0\26\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\4\22\1\u0128\21\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\5\22\1\u0129"+ + "\2\22\1\u012a\15\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\5\22\1\u012b"+ + "\20\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\10\22\1\u012c\15\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\7\22\1\u012d\3\0\26\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\u012e\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\1\22\1\u012f\24\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\11\22\1\u0130\14\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22"+ + "\1\u0131\3\0\26\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\14\22\1\u0132"+ + "\11\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\u0133\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\6\22\1\u0134\17\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\5\22"+ + "\1\u0135\20\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u0136\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\10\22\1\u0137\15\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u0138"+ + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\6\22\1\u0139\5\22"+ + "\1\u013a\11\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u013b\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\2\22\1\u013c\23\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u013d"+ + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u013e\23\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\16\22\1\u013f\7\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\14\22\1\u0140\11\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\u0141\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\22\22\1\u0142\3\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\3\22\1\u0143\22\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\14\22\1\u0144\11\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\13\22"+ + "\1\u0145\12\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\11\22\1\u0146\14\22"+ + "\14\0\1\22\21\0\2\u0147\3\0\3\u0147\5\0\1\u0147"+ + "\2\0\5\u0147\3\0\1\u0147\1\0\1\u0147\1\0\1\u0147"+ + "\6\0\1\u0147\50\0\2\u0148\3\0\3\u0148\5\0\1\u0148"+ + "\2\0\5\u0148\3\0\1\u0148\1\0\1\u0148\1\0\1\u0148"+ + "\6\0\1\u0148\31\0\2\u0149\5\0\2\u0114\1\0\1\u0149"+ + "\1\0\1\u0114\1\u014a\4\u0114\2\0\4\u0114\4\0\10\u0114"+ + "\3\0\26\u0114\33\0\1\u014b\123\0\1\u014c\76\0\2\u0118"+ + "\3\0\1\u0118\1\0\4\u0118\2\0\4\u0118\4\0\10\u0118"+ + "\3\0\26\u0118\16\0\4\322\1\321\1\u011b\106\322\20\0"+ + "\2\u014d\3\0\3\u014d\5\0\1\u014d\2\0\5\u014d\3\0"+ + "\1\u014d\1\0\1\u014d\1\0\1\u014d\6\0\1\u014d\41\0"+ + "\1\150\7\0\1\166\13\0\1\u014e\3\0\2\u014e\2\164"+ + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22"+ + "\1\u014f\3\0\26\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\14\22\1\u0150"+ + "\11\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\10\22\1\u0151\15\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\7\22\1\u0152\16\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\3\22\1\u0153\22\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\1\22\1\u0154"+ + "\24\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\16\22\1\u0155\7\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\10\22\1\u0156\15\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\11\22\1\u0157\14\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\5\22\1\u0158"+ + "\20\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\11\22\1\u0159\14\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\1\22\1\u015a\24\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\4\22\1\u015b\21\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\1\22\1\u015c"+ + "\24\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\22\22\1\u015d\3\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\5\22\1\u015e\20\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\15\22\1\u015f\10\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\6\22\1\u0160"+ + "\17\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\2\22\1\u0161\23\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\1\22\1\u0162\24\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\1\22\1\u0163\24\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\7\22\1\u0164\3\0\26\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\3\22\1\u0165\4\22\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\12\22\1\u0166\13\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\u0167\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\21\22\1\u0168\4\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\u0169\3\0\26\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u016a"+ + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u016b\23\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\2\22\1\u016c\23\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\11\22\1\u016d\14\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\7\22"+ + "\1\u016e\16\22\14\0\1\22\2\0\2\u0149\10\0\1\u0149"+ + "\2\0\1\u014a\123\0\1\u016f\105\0\2\u0170\3\0\3\u0170"+ + "\5\0\1\u0170\2\0\5\u0170\3\0\1\u0170\1\0\1\u0170"+ + "\1\0\1\u0170\6\0\1\u0170\41\0\1\150\7\0\1\166"+ + "\13\0\1\u0171\3\0\2\u0171\2\164\55\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\14\22\1\u0172"+ + "\11\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\11\22\1\u0173\14\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\13\22\1\u0174\12\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\7\22\1\u0175\16\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\7\22\1\u0176"+ + "\16\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\4\22\1\u0177\21\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\16\22\1\u0178\7\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\11\22\1\u0179\14\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\7\22\1\u017a\3\0\26\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\17\22\1\u017b\6\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\3\22"+ + "\1\u017c\4\22\3\0\26\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\7\22"+ + "\1\u017d\16\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\3\22\1\u017e\4\22\3\0\7\22"+ + "\1\u017f\16\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\10\22\1\u0180\15\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\21\22\1\u0181\4\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\11\22\1\u0182\14\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\14\22"+ + "\1\u0183\11\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u0184\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\11\22\1\u0185\14\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\4\22\1\u0186\21\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u0187"+ + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\23\22\1\u0188\2\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\4\22\1\u0189\21\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\11\22\1\u018a\14\22\14\0\1\22\30\0\1\u018b\104\0"+ + "\2\u018c\3\0\3\u018c\5\0\1\u018c\2\0\5\u018c\3\0"+ + "\1\u018c\1\0\1\u018c\1\0\1\u018c\6\0\1\u018c\41\0"+ + "\1\150\7\0\1\166\13\0\1\u018d\3\0\2\u018d\2\164"+ + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\20\22\1\u018e\5\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\6\22"+ + "\1\u018f\17\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\5\22\1\u0190\20\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\12\22\1\u0191\13\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\13\22\1\u0192\12\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22"+ + "\1\u0193\23\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\4\22\1\u0194\21\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\2\22\1\u0195\23\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\2\22\1\u0196\23\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u0197\3\0"+ + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\7\22\1\u0198\16\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\10\22\1\u0199\15\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\4\22\1\u019a\21\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u019b"+ + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\u019c\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22"+ + "\1\u019d\3\0\26\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u019e"+ + "\15\22\14\0\1\22\31\0\1\u019f\103\0\2\u01a0\3\0"+ + "\3\u01a0\5\0\1\u01a0\2\0\5\u01a0\3\0\1\u01a0\1\0"+ + "\1\u01a0\1\0\1\u01a0\6\0\1\u01a0\41\0\1\150\7\0"+ + "\1\166\13\0\1\u01a1\3\0\2\u01a1\2\164\55\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\7\22"+ + "\1\u01a2\16\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u01a3\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\7\22\1\u01a4\3\0\26\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\4\22"+ + "\1\u01a5\21\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u01a6\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\4\22\1\u01a7\21\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\14\22\1\u01a8\11\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\7\22\1\u01a9"+ + "\16\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\u01aa\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22"+ + "\1\u01ab\3\0\26\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\20\22\1\u01ac"+ + "\5\22\14\0\1\22\30\0\1\u01ad\104\0\2\u01ae\3\0"+ + "\3\u01ae\5\0\1\u01ae\2\0\5\u01ae\3\0\1\u01ae\1\0"+ + "\1\u01ae\1\0\1\u01ae\6\0\1\u01ae\41\0\1\150\7\0"+ + "\1\166\13\0\1\u01af\3\0\2\u01af\2\164\55\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u01b0\3\0"+ + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\6\22\1\u01b1\17\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\7\22\1\u01b2\3\0\26\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\u01b3\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\13\22\1\u01b4\12\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\13\22\1\u01b5\12\22\14\0\1\22"+ + "\25\0\1\u01b6\107\0\2\u01b7\3\0\3\u01b7\5\0\1\u01b7"+ + "\2\0\5\u01b7\3\0\1\u01b7\1\0\1\u01b7\1\0\1\u01b7"+ + "\6\0\1\u01b7\41\0\1\150\7\0\1\166\13\0\1\u01b8"+ + "\3\0\2\u01b8\2\164\55\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\3\22\1\u01b9\4\22\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\5\22\1\u01ba\20\22\14\0\1\22\12\0"+ + "\1\150\7\0\1\166\13\0\1\u01bb\3\0\2\u01bb\2\164"+ + "\60\0\1\150\7\0\1\166\13\0\1\u01bc\3\0\2\u01bc"+ + "\2\164\60\0\1\150\7\0\1\166\13\0\1\u01bd\3\0"+ + "\2\u01bd\2\164\60\0\1\150\7\0\1\166\13\0\1\u01be"+ + "\3\0\2\u01be\2\164\60\0\1\150\7\0\1\166\13\0"+ + "\1\u01bf\3\0\2\u01bf\2\164\60\0\1\150\7\0\1\166"+ + "\13\0\1\u01c0\3\0\2\u01c0\2\164\47\0"; + + private static int [] zzUnpackTrans() { + int [] result = new int[23180]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\13\0\1\11\1\1\1\11\13\1\3\11\1\1\2\11"+ + "\26\1\7\11\4\1\1\11\2\1\2\11\3\1\1\11"+ + "\1\1\1\11\3\1\2\11\1\1\1\11\2\1\1\11"+ + "\1\1\2\11\2\1\1\11\2\1\1\11\2\1\1\11"+ + "\1\1\1\0\2\11\1\1\1\11\1\1\1\11\2\1"+ + "\2\11\1\1\2\11\1\1\2\11\1\0\3\1\1\0"+ + "\11\1\2\11\1\0\44\1\11\11\1\1\6\11\1\1"+ + "\1\11\1\0\1\11\1\0\1\11\1\0\2\11\1\0"+ + "\1\1\4\0\1\1\2\0\2\11\4\1\1\11\2\0"+ + "\3\11\1\1\1\11\1\0\1\1\1\11\62\1\3\0"+ + "\3\11\1\0\1\11\2\0\1\1\2\11\1\0\1\11"+ + "\52\1\1\11\2\0\2\11\1\0\42\1\1\0\33\1"+ + "\1\0\23\1\1\0\15\1\1\0\10\1\2\11\11\1"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[448]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /** + * The number of occupied positions in zzBuffer beyond zzEndRead. + * When a lead/high surrogate has been read from the input stream + * into the final zzBuffer position, this will have a value of 1; + * otherwise, it will have a value of 0. + */ + private int zzFinalHighSurrogate = 0; + + /* user code: */ + + private String sourceCode; + + public ActionScriptLexer(String sourceCode){ + this(new StringReader(sourceCode)); + this.sourceCode = sourceCode; + } + + public void yypushbackstr(String s, int state) + { + sourceCode = s + sourceCode.substring(yychar + yylength()); + yyreset(new StringReader(sourceCode)); + yybegin(state); + } + + public void yypushbackstr(String s) + { + yypushbackstr(s, YYINITIAL); + } + + StringBuffer string = new StringBuffer(); + + private static String xmlTagName = ""; + + public int yychar() { + return yychar; + } + + private Stack pushedBack = new Stack<>(); + + public int yyline() { + return yyline + 1; + } + + private List listeners=new ArrayList<>(); + + public void addListener(LexListener listener){ + listeners.add(listener); + } + + public void removeListener(LexListener listener){ + listeners.remove(listener); + } + + public void informListenersLex(ParsedSymbol s){ + for(LexListener l:listeners){ + l.onLex(s); + } + } + + public void informListenersPushBack(ParsedSymbol s){ + for(LexListener l:listeners){ + l.onPushBack(s); + } + } + + public void pushback(ParsedSymbol symb) { + pushedBack.push(symb); + last = null; + informListenersPushBack(symb); + } + + ParsedSymbol last; + public ParsedSymbol lex() throws java.io.IOException, AVM2ParseException{ + ParsedSymbol ret = null; + if (!pushedBack.isEmpty()){ + ret = last = pushedBack.pop(); + } else { + ret = last = yylex(); + } + informListenersLex(ret); + return ret; + } + + + + /** + * Creates a new scanner + * + * @param in the java.io.Reader to read input from. + */ + public ActionScriptLexer(java.io.Reader in) { + this.zzReader = in; + } + + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x110000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 3140) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { + /* if not: blow it up */ + char newBuffer[] = new char[zzBuffer.length*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + } + + /* fill the buffer with new input */ + int requested = zzBuffer.length - zzEndRead; + int totalRead = 0; + while (totalRead < requested) { + int numRead = zzReader.read(zzBuffer, zzEndRead + totalRead, requested - totalRead); + if (numRead == -1) { + break; + } + totalRead += numRead; + } + + if (totalRead > 0) { + zzEndRead += totalRead; + if (totalRead == requested) { /* possibly more input available */ + if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { + --zzEndRead; + zzFinalHighSurrogate = 1; + } + } + return false; + } + + // totalRead = 0: End of stream + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * Internal scan buffer is resized down to its initial length, if it has grown. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + zzFinalHighSurrogate = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + if (zzBuffer.length > ZZ_BUFFERSIZE) + zzBuffer = new char[ZZ_BUFFERSIZE]; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public ParsedSymbol yylex() throws java.io.IOException, AVM2ParseException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar+= zzMarkedPosL-zzStartRead; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + // set up zzAction for empty match case: + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + } + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); + } + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 1: + { + } + case 165: break; + case 2: + { yyline++; + } + case 166: break; + case 3: + { /*ignore*/ + } + case 167: break; + case 4: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); + } + case 168: break; + case 5: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); + } + case 169: break; + case 6: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); + } + case 170: break; + case 7: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); + } + case 171: break; + case 8: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); + } + case 172: break; + case 9: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); + } + case 173: break; + case 10: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); + } + case 174: break; + case 11: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); + } + case 175: break; + case 12: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); + } + case 176: break; + case 13: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); + } + case 177: break; + case 14: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); + } + case 178: break; + case 15: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); + } + case 179: break; + case 16: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); + } + case 180: break; + case 17: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); + } + case 181: break; + case 18: + { string.setLength(0); + yybegin(STRING); + } + case 182: break; + case 19: + { string.setLength(0); + yybegin(CHARLITERAL); + } + case 183: break; + case 20: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); + } + case 184: break; + case 21: + { string.setLength(0); + yybegin(OIDENTIFIER); + } + case 185: break; + case 22: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); + } + case 186: break; + case 23: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); + } + case 187: break; + case 24: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); + } + case 188: break; + case 25: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); + } + case 189: break; + case 26: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); + } + case 190: break; + case 27: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); + } + case 191: break; + case 28: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); + } + case 192: break; + case 29: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); + } + case 193: break; + case 30: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); + } + case 194: break; + case 31: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); + } + case 195: break; + case 32: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); + } + case 196: break; + case 33: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); + } + case 197: break; + case 34: + { string.append(yytext()); + } + case 198: break; + case 35: + { yybegin(YYINITIAL); yyline++; + } + case 199: break; + case 36: + { yybegin(YYINITIAL); + // length also includes the trailing quote + return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); + } + case 200: break; + case 37: + { yybegin(YYINITIAL); yyline++; + } + case 201: break; + case 38: + { string.append(yytext()); yyline++; + } + case 202: break; + case 39: + { yybegin(XML); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_END, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 203: break; + case 40: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRNAMEVAR_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 204: break; + case 41: + { yybegin(YYINITIAL); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRVALVAR_BEGIN, yytext()); + } + case 205: break; + case 42: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRNAMEVAR_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 206: break; + case 43: + { yybegin(YYINITIAL); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRVALVAR_BEGIN, yytext()); + } + case 207: break; + case 44: + { string.append(yytext()); yyline++; + } + case 208: break; + case 45: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_VAR_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 209: break; + case 46: + { yybegin(YYINITIAL); + // length also includes the trailing quote + return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); + } + case 210: break; + case 47: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); + } + case 211: break; + case 48: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); + } + case 212: break; + case 49: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DESCENDANTS, yytext()); + } + case 213: break; + case 50: + { return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, yytext()); + } + case 214: break; + case 51: + { return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); + } + case 215: break; + case 52: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FILTER, yytext()); + } + case 216: break; + case 53: + { yybegin(XMLOPENTAG); + string.setLength(0); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext()); + } + case 217: break; + case 54: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); + } + case 218: break; + case 55: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); + } + case 219: break; + case 56: + { return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext()); + } + case 220: break; + case 57: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); + } + case 221: break; + case 58: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); + } + case 222: break; + case 59: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); + } + case 223: break; + case 60: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); + } + case 224: break; + case 61: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); + } + case 225: break; + case 62: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); + } + case 226: break; + case 63: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); + } + case 227: break; + case 64: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); + } + case 228: break; + case 65: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); + } + case 229: break; + case 66: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); + } + case 230: break; + case 67: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); + } + case 231: break; + case 68: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IF, yytext()); + } + case 232: break; + case 69: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); + } + case 233: break; + case 70: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IN, yytext()); + } + case 234: break; + case 71: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DO, yytext()); + } + case 235: break; + case 72: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); + } + case 236: break; + case 73: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); + } + case 237: break; + case 74: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); + } + case 238: break; + case 75: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); + } + case 239: break; + case 76: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); + } + case 240: break; + case 77: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); + } + case 241: break; + case 78: + { /* ignore illegal character escape */ + } + case 242: break; + case 79: + { string.append('\"'); + } + case 243: break; + case 80: + { string.append('\''); + } + case 244: break; + case 81: + { string.append('\f'); + } + case 245: break; + case 82: + { string.append('\\'); + } + case 246: break; + case 83: + { string.append('\b'); + } + case 247: break; + case 84: + { string.append('\r'); + } + case 248: break; + case 85: + { string.append('\n'); + } + case 249: break; + case 86: + { string.append('\t'); + } + case 250: break; + case 87: + { yybegin(XML); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTFINISHTAG_END, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 251: break; + case 88: + { yybegin(XMLOPENTAGATTRIB); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTENAME, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 252: break; + case 89: + { yybegin(XMLOPENTAG); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); + } + case 253: break; + case 90: + { yybegin(XMLINSTRATTRIB); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTENAME, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 254: break; + case 91: + { yybegin(XML); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTR_END, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 255: break; + case 92: + { yybegin(XMLINSTROPENTAG); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); + } + case 256: break; + case 93: + { yybegin(XMLOPENTAG); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 257: break; + case 94: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 258: break; + case 95: + { throw new AVM2ParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); + } + case 259: break; + case 96: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); + } + case 260: break; + case 97: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); + } + case 261: break; + case 98: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); + } + case 262: break; + case 99: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); + } + case 263: break; + case 100: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); + } + case 264: break; + case 101: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); + } + case 265: break; + case 102: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); + } + case 266: break; + case 103: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FOR, yytext()); + } + case 267: break; + case 104: + { return new ParsedSymbol(SymbolGroup.PREPROCESSOR, SymbolType.PREPROCESSOR, yytext().substring(2)); + } + case 268: break; + case 105: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.SET, yytext()); + } + case 269: break; + case 106: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); + } + case 270: break; + case 107: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRY, yytext()); + } + case 271: break; + case 108: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.USE, yytext()); + } + case 272: break; + case 109: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.VAR, yytext()); + } + case 273: break; + case 110: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.GET, yytext()); + } + case 274: break; + case 111: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); + } + case 275: break; + case 112: + { string.append(yytext()); + yybegin(XML); + String ret = string.toString(); + string.setLength(0); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_CDATA, ret); + } + case 276: break; + case 113: + { string.append(yytext()); + yybegin(XML); + String ret = string.toString(); + string.setLength(0); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_COMMENT, ret); + } + case 277: break; + case 114: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHVARTAG_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 278: break; + case 115: + { yybegin(XMLINSTROPENTAG); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTR_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 279: break; + case 116: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRVARTAG_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 280: break; + case 117: + { string.append('\u00A7'); + } + case 281: break; + case 118: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); + } + case 282: break; + case 119: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.EACH, yytext()); + } + case 283: break; + case 120: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.ELSE, yytext()); + } + case 284: break; + case 121: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CASE, yytext()); + } + case 285: break; + case 122: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); + } + case 286: break; + case 123: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); + } + case 287: break; + case 124: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); + } + case 288: break; + case 125: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WITH, yytext()); + } + case 289: break; + case 126: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); + } + case 290: break; + case 127: + { char val = (char) Integer.parseInt(yytext().substring(2), 16); + string.append(val); + } + case 291: break; + case 128: + { pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHTAG, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 292: break; + case 129: + { String ret = string.toString(); string.setLength(0); string.append(yytext()); yybegin(XMLCOMMENT); + if (!ret.isEmpty()) return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, ret); + } + case 293: break; + case 130: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); + } + case 294: break; + case 131: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.FINAL, yytext()); + } + case 295: break; + case 132: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.BREAK, yytext()); + } + case 296: break; + case 133: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CATCH, yytext()); + } + case 297: break; + case 134: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONST, yytext()); + } + case 298: break; + case 135: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CLASS, yytext()); + } + case 299: break; + case 136: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SUPER, yytext()); + } + case 300: break; + case 137: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THROW, yytext()); + } + case 301: break; + case 138: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WHILE, yytext()); + } + case 302: break; + case 139: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.RETURN, yytext()); + } + case 303: break; + case 140: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.STATIC, yytext()); + } + case 304: break; + case 141: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SWITCH, yytext()); + } + case 305: break; + case 142: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.NATIVE, yytext()); + } + case 306: break; + case 143: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); + } + case 307: break; + case 144: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPORT, yytext()); + } + case 308: break; + case 145: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); + } + case 309: break; + case 146: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PUBLIC, yytext()); + } + case 310: break; + case 147: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FINALLY, yytext()); + } + case 311: break; + case 148: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EXTENDS, yytext()); + } + case 312: break; + case 149: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DEFAULT, yytext()); + } + case 313: break; + case 150: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.DYNAMIC, yytext()); + } + case 314: break; + case 151: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PRIVATE, yytext()); + } + case 315: break; + case 152: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PACKAGE, yytext()); + } + case 316: break; + case 153: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FUNCTION, yytext()); + } + case 317: break; + case 154: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONTINUE, yytext()); + } + case 318: break; + case 155: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.OVERRIDE, yytext()); + } + case 319: break; + case 156: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERNAL, yytext()); + } + case 320: break; + case 157: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); + } + case 321: break; + case 158: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE, yytext()); + } + case 322: break; + case 159: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERFACE, yytext()); + } + case 323: break; + case 160: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); + } + case 324: break; + case 161: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PROTECTED, yytext()); + } + case 325: break; + case 162: + { String ret = string.toString(); string.setLength(0); string.append(yytext() ); yybegin(XMLCDATA); + if (!ret.isEmpty()) return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, ret); + } + case 326: break; + case 163: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); + } + case 327: break; + case 164: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPLEMENTS, yytext()); + } + case 328: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { + return new ParsedSymbol(SymbolGroup.EOF, SymbolType.EOF, null); + } + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolGroup.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolGroup.java index e2342d094..7c5cc7b27 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolGroup.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolGroup.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; /** @@ -32,5 +33,6 @@ public enum SymbolGroup { TYPENAME, EOF, //GLOBALFUNC, - GLOBALCONST + GLOBALCONST, + PREPROCESSOR } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java index 4b06b8220..066fcbf48 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java @@ -1,242 +1,243 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.parser.script; - -import com.jpexs.decompiler.graph.GraphTargetItem; - -/** - * - * @author JPEXS - */ -public enum SymbolType { - //Keywords - - BREAK, - CASE, - CONTINUE, - DEFAULT, - DO, - WHILE, - ELSE, - FOR, - EACH, - IN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IF, - RETURN, - SUPER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SWITCH, - THROW, - TRY, - CATCH, - FINALLY, - WITH, - DYNAMIC, - INTERNAL, - OVERRIDE, - PRIVATE, - PROTECTED, - PUBLIC, - STATIC, - CLASS, - CONST, - EXTENDS, - FUNCTION(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GET, - IMPLEMENTS, - INTERFACE, - NAMESPACE, - PACKAGE, - SET, - VAR, - IMPORT, - USE, - FALSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NULL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - THIS(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TRUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //Operators - PARENT_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PARENT_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SEMICOLON, - COMMA(GraphTargetItem.PRECEDENCE_COMMA, false), - REST, - DOT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - ASSIGN(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - GREATER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - LOWER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT(GraphTargetItem.PRECEDENCE_UNARY, false), - NEGATE(GraphTargetItem.PRECEDENCE_UNARY, false), - TERNAR(GraphTargetItem.PRECEDENCE_CONDITIONAL, true, true), /*!! ternar !!!*/ - COLON(GraphTargetItem.PRECEDENCE_CONDITIONAL, false),/*!! ternar !!!*/ - EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - LOWER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - GREATER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - AND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), - OR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), - INCREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false),//OR Unary - DECREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false), //OR Unary - PLUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), - MINUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), //OR Unary - MULTIPLY(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - DIVIDE(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - BITAND(GraphTargetItem.PRECEDENCE_BITWISEAND, true), - BITOR(GraphTargetItem.PRECEDENCE_BITWISEOR, true), - XOR(GraphTargetItem.PRECEDENCE_BITWISEXOR, true), - MODULO(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_LEFT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - ASSIGN_PLUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MINUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MULTIPLY(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_DIVIDE(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITAND(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_XOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MODULO(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_LEFT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - AS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - DELETE(GraphTargetItem.PRECEDENCE_UNARY, false), - INSTANCEOF(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NAMESPACE_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEW(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPEOF(GraphTargetItem.PRECEDENCE_UNARY, false), - VOID, - ATTRIBUTE, - //Other - STRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), - COMMENT, - //XML, - IDENTIFIER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - INTEGER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - DOUBLE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - EOF, - //TRACE, - //GETURL, - //GOTOANDSTOP, - //NEXTFRAME, - //PLAY, - //PREVFRAME, - //TELLTARGET, - //STOP, - //STOPALLSOUNDS, - //TOGGLEHIGHQUALITY, - //ORD, - //CHR, - //DUPLICATEMOVIECLIP, - //STOPDRAG, - //GETTIMER, - //LOADVARIABLES, - //LOADMOVIE, - //GOTOANDPLAY, - //MBORD, - //MBCHR, - //MBLENGTH, - //MBSUBSTRING, - //RANDOM, - //REMOVEMOVIECLIP, - //STARTDRAG, - //SUBSTR, - //LENGTH, //string.length - INT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //TARGETPATH, - NUMBER_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STRING_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //IFFRAMELOADED, - INFINITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //EVAL, - UNDEFINED(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //NEWLINE, - NAN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //GETVERSION, - //CALL, - //LOADMOVIENUM, - //LOADVARIABLESNUM, - //PRINT, - //PRINTNUM, - //PRINTASBITMAP, - //PRINTASBITMAPNUM, - //UNLOADMOVIE, - //UNLOADMOVIENUM, - FINAL, - XML_STARTTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_FINISHVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_STARTFINISHTAG_END(GraphTargetItem.PRECEDENCE_PRIMARY, false), // /> - XML_COMMENT(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_CDATA(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_INSTR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_VAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // { - XML_ATTRIBUTENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa= - XML_ATTRIBUTEVALUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), // "vvv" - XML_TEXT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - XML_ATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= - XML_ATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ - XML_INSTRATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= - XML_INSTRATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ - XML_INSTRVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_FINISHVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_STARTFINISHTAG_END(GraphTargetItem.PRECEDENCE_PRIMARY, false), // /> + XML_COMMENT(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_CDATA(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_INSTR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_VAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // { + XML_ATTRIBUTENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa= + XML_ATTRIBUTEVALUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), // "vvv" + XML_TEXT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + XML_ATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= + XML_ATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ + XML_INSTRATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= + XML_INSTRATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ + XML_INSTRVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // propertyNamesList = Arrays.asList(propertyNames); - - private static final Logger logger = Logger.getLogger(Action.class.getName()); - - /** - * Constructor - * - * @param actionCode Action type identifier - * @param actionLength Length of action data - */ - public Action(int actionCode, int actionLength) { - this.actionCode = actionCode; - this.actionLength = actionLength; - } - - public Action() { - } - - /** - * Returns address of this action - * - * @return address of this action - */ - public long getAddress() { - return address; - } - - /** - * Gets all addresses which are referenced from this action and/or - * subactions - * - * @param refs list of addresses - */ - public void getRef(Set refs) { - } - - /** - * Gets all addresses which are referenced from the list of actions - * - * @param list List of actions - * @return List of addresses - */ - public static Set getActionsAllRefs(List list) { - Set ret = new HashSet<>(); - for (Action a : list) { - a.getRef(ret); - } - return ret; - } - - public int getTotalActionLength() { - return actionLength + 1 + ((actionCode >= 0x80) ? 2 : 0); - } - - /** - * Sets address of this instruction - * - * @param address Address - */ - public void setAddress(long address) { - this.address = address; - } - - /** - * Returns a string representation of the object - * - * @return a string representation of the object. - */ - @Override - public String toString() { - return "Action" + actionCode; - } - - /** - * Reads String from FlasmLexer - * - * @param lex FlasmLexer - * @return String value - * @throws IOException - * @throws ActionParseException When read object is not String - */ - protected String lexString(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_STRING) { - throw new ActionParseException("String expected", lex.yyline()); - } - return (String) symb.value; - } - - /** - * Reads Block startServer from FlasmLexer - * - * @param lex FlasmLexer - * @throws IOException - * @throws ActionParseException When read object is not Block startServer - */ - protected void lexBlockOpen(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_BLOCK_START) { - throw new ActionParseException("Block startServer ", lex.yyline()); - } - } - - /** - * Reads Identifier from FlasmLexer - * - * @param lex FlasmLexer - * @return Identifier name - * @throws IOException - * @throws ActionParseException When read object is not Identifier - */ - protected String lexIdentifier(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_IDENTIFIER) { - throw new ActionParseException("Identifier expected", lex.yyline()); - } - return (String) symb.value; - } - - /** - * Reads long value from FlasmLexer - * - * @param lex FlasmLexer - * @return long value - * @throws IOException - * @throws ActionParseException When read object is not long value - */ - protected long lexLong(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_INTEGER) { - throw new ActionParseException("Integer expected", lex.yyline()); - } - return (Long) symb.value; - } - - /** - * Reads boolean value from FlasmLexer - * - * @param lex FlasmLexer - * @return boolean value - * @throws IOException - * @throws ActionParseException When read object is not boolean value - */ - protected boolean lexBoolean(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_BOOLEAN) { - throw new ActionParseException("Boolean expected", lex.yyline()); - } - return (Boolean) symb.value; - } - - /** - * Gets action converted to bytes - * - * @param version SWF version - * @return Array of bytes - */ - public byte[] getBytes(int version) { - return surroundWithAction(new byte[0], version); - } - - /** - * Gets the length of action converted to bytes - * - * @param version SWF version - * @return Length - */ - public int getBytesLength(int version) { - return getBytes(version).length; - } - - /** - * Uptates the action length to the length calculated from action bytes - * - * @param version SWF version - */ - public void updateLength(int version) { - int length = getBytes(version).length; - actionLength = length - 1 - ((actionCode >= 0x80) ? 2 : 0); - } - - /** - * Surrounds byte array with Action header - * - * @param data Byte array - * @param version SWF version - * @return Byte array - */ - protected byte[] surroundWithAction(byte[] data, int version) { - ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - SWFOutputStream sos2 = new SWFOutputStream(baos2, version); - try { - sos2.writeUI8(actionCode); - if (actionCode >= 0x80) { - sos2.writeUI16(data.length); - } - sos2.write(data); - sos2.close(); - } catch (IOException e) { - throw new Error("This should never happen.", e); - } - return baos2.toByteArray(); - } - - /** - * Converts list of Actions to bytes - * - * @param list List of actions - * @param addZero Whether or not to add 0 UI8 value to the end - * @param version SWF version - * @return Array of bytes - */ - public static byte[] actionsToBytes(List list, boolean addZero, int version) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Action lastAction = null; - for (Action a : list) { - try { - lastAction = a; - baos.write(a.getBytes(version)); - } catch (IOException e) { - } - } - if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { - baos.write(0); - } - return baos.toByteArray(); - } - - /** - * Set addresses of actions in the list - * - * @param list List of actions - * @param baseAddress Address of first action in the list - */ - public static void setActionsAddresses(List list, long baseAddress) { - long offset = baseAddress; - for (Action a : list) { - a.setAddress(offset); - offset += a.getTotalActionLength(); - } - } - - /** - * Converts list of actions to ASM source - * - * @param listeners - * @param address - * @param list List of actions - * @param version SWF version - * @param exportMode PCode or hex? - * @return source ASM - * - */ - public static String actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode) { - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - actionsToString(listeners, address, list, version, exportMode, writer); - return writer.toString(); - } - - /** - * Converts list of actions to ASM source - * - * @param listeners - * @param address - * @param list List of actions - * @param version SWF version - * @param exportMode PCode or hex? - * @param writer - * @return GraphTextWriter - */ - public static GraphTextWriter actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - if (exportMode == ScriptExportMode.CONSTANTS) { - return constantPoolActionsToString(listeners, address, list, version, exportMode, writer); - } - - long offset; - Set importantOffsets = getActionsAllRefs(list); - /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); - if (!cps.isEmpty()) { - setConstantPool(list, cps.get(cps.size() - 1)); - }*/ - HashMap> containers = new HashMap<>(); - HashMap containersPos = new HashMap<>(); - offset = address; - int pos = 0; - boolean lastPush = false; - for (Action a : list) { - if (pos % INFORM_LISTENER_RESOLUTION == 0) { - for (DisassemblyListener listener : listeners) { - listener.progressToString(pos + 1, list.size()); - } - } - - if (exportMode == ScriptExportMode.PCODE_HEX) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("; "); - writer.appendNoHilight(Helper.bytesToHexString(a.getBytes(version))); - writer.newLine(); - } - - offset = a.getAddress(); - - if ((!(a.isIgnored())) && (a instanceof GraphSourceItemContainer)) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - containersPos.put(cnt, 0); - List sizes = cnt.getContainerSizes(); - long addr = ((Action) cnt).getAddress() + cnt.getHeaderSize(); - for (Long size : sizes) { - addr += size; - if (size == 0) { - continue; - } - if (!containers.containsKey(addr)) { - containers.put(addr, new ArrayList()); - } - containers.get(addr).add(cnt); - } - } - - if (containers.containsKey(offset)) { - for (int i = 0; i < containers.get(offset).size(); i++) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("}").newLine(); - GraphSourceItemContainer cnt = containers.get(offset).get(i); - int cntPos = containersPos.get(cnt); - writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); - cntPos++; - containersPos.put(cnt, cntPos); - } - } - - if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("loc"); - writer.appendNoHilight(Helper.formatAddress(offset)); - writer.appendNoHilight(":"); - } - - if (a.isIgnored()) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - if (!(a instanceof ActionEnd)) { - int len = a.getTotalActionLength(); - for (int i = 0; i < len; i++) { - writer.appendNoHilight("Nop").newLine(); - } - } - } else { - //if (!(a instanceof ActionNop)) { - String add = ""; - // honfika: commented out the following lines, because it makes no sense - /*if (a instanceof ActionIf) { - add = " change: " + ((ActionIf) a).getJumpOffset(); - } - if (a instanceof ActionJump) { - add = " change: " + ((ActionJump) a).getJumpOffset(); - } - add = "; ofs" + Helper.formatAddress(offset) + add; - add = "";*/ - if ((a instanceof ActionPush) && lastPush) { - writer.appendNoHilight(" "); - ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, exportMode, writer); - } else { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - - writer.append("", offset); - - int fixBranch = -1; - if (a instanceof ActionIf) { - ActionIf aif = (ActionIf) a; - if (aif.jumpUsed && !aif.ignoreUsed) { - fixBranch = 0; - } - if (!aif.jumpUsed && aif.ignoreUsed) { - fixBranch = 1; - } - } - - if (fixBranch > -1) { - writer.appendNoHilight("FFDec_DeobfuscatePop"); - if (fixBranch == 0) { //jump - writer.newLine(); - writer.appendNoHilight("Jump loc"); - writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getTotalActionLength() + ((ActionIf) a).getJumpOffset())); - } else { - //nojump, ignore - } - } else { - a.getASMSourceReplaced(list, importantOffsets, exportMode, writer); - } - writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); - writer.appendNoHilight(add); - if (!(a instanceof ActionPush)) { - writer.newLine(); - } - } - if (a instanceof ActionPush) { - lastPush = true; - } else { - lastPush = false; - } - //} - } - - offset += a.getTotalActionLength(); - pos++; - } - if (lastPush) { - writer.newLine(); - } - - if (containers.containsKey(offset)) { - for (int i = 0; i < containers.get(offset).size(); i++) { - writer.appendNoHilight("}"); - writer.newLine(); - GraphSourceItemContainer cnt = containers.get(offset).get(i); - int cntPos = containersPos.get(cnt); - writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); - cntPos++; - containersPos.put(cnt, cntPos); - } - } - - if (importantOffsets.contains(offset)) { - writer.appendNoHilight("loc"); - writer.appendNoHilight(Helper.formatAddress(offset)); - writer.appendNoHilight(":"); - writer.newLine(); - } - - return writer; - } - - public static GraphTextWriter constantPoolActionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - int poolIdx = 0; - writer.appendNoHilight(Helper.constants).newLine(); - for (Action a : list) { - if (a instanceof ActionConstantPool) { - if (poolIdx > 0) { - writer.appendNoHilight("---").newLine(); - } - - ActionConstantPool cPool = (ActionConstantPool) a; - int constIdx = 0; - for (String c : cPool.constantPool) { - writer.appendNoHilight(constIdx); - writer.appendNoHilight("|"); - writer.appendNoHilight(Helper.escapeString(c)); - writer.newLine(); - constIdx++; - } - - poolIdx++; - } - } - - return writer; - } - - /** - * Convert action to ASM source - * - * @param container - * @param knownAddreses List of important offsets to mark as labels - * @param exportMode PCode or hex? - * @return String of P-code source - */ - public String getASMSource(ActionList container, Set knownAddreses, ScriptExportMode exportMode) { - return toString(); - } - - /** - * Translates this function to stack and output. - * - * @param stack Stack - * @param output Output - * @param regNames Register names - * @param variables Variables - * @param functions Functions - * @param staticOperation the value of staticOperation - * @param path the value of path - * @throws java.lang.InterruptedException - */ - public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) throws InterruptedException { - } - - /** - * Pops long value off the stack - * - * @param stack Stack - * @return long value - */ - protected long popLong(TranslateStack stack) { - GraphTargetItem item = stack.pop(); - if (item instanceof DirectValueActionItem) { - if (((DirectValueActionItem) item).value instanceof Long) { - return (long) (Long) ((DirectValueActionItem) item).value; - } - } - return 0; - } - - /** - * Converts action index to address in the specified list of actions - * - * @param actions List of actions - * @param ip Action index - * @return address - */ - public static long ip2adr(List actions, int ip) { - /* List actions=new ArrayList(); - for(GraphSourceItem s:sources){ - if(s instanceof Action){ - actions.add((Action)s); - } - }*/ - if (ip >= actions.size()) { - if (actions.isEmpty()) { - return 0; - } - return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); - } - if (ip == -1) { - return 0; - } - return actions.get(ip).getAddress(); - } - - /** - * Converts address to action index in the specified list of actions - * - * @param actions List of actions - * @param addr Address - * @return action index - */ - public static int adr2ip(List actions, long addr) { - for (int ip = 0; ip < actions.size(); ip++) { - if (actions.get(ip).getAddress() == addr) { - return ip; - } - } - if (actions.size() > 0) { - long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); - if (addr == outpos) { - return actions.size(); - } - } - return -1; - } - - public static List actionsToTree(List actions, int version, int staticOperation, String path) throws InterruptedException { - return actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); - } - - /** - * Converts list of actions to ActionScript source code - * - * @param asm - * @param actions List of actions - * @param path - * @return source - * @throws java.lang.InterruptedException - */ - public static String actionsToSource(final ASMSource asm, final List actions, final String path) throws InterruptedException { - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - actionsToSource(asm, actions, path, writer); - return writer.toString(); - } - - /** - * Converts list of actions to ActionScript source code - * - * @param asm - * @param actions List of actions - * @param path - * @param writer - * @throws java.lang.InterruptedException - */ - public static void actionsToSource(final ASMSource asm, final List actions, final String path, GraphTextWriter writer) throws InterruptedException { - writer.suspendMeasure(); - List tree = null; - Throwable convertException = null; - int timeout = Configuration.decompilationTimeoutSingleMethod.get(); - final int version = asm == null ? SWF.DEFAULT_VERSION : asm.getSwf().version; - try { - tree = CancellableWorker.call(new Callable>() { - @Override - public List call() throws Exception { - 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); - Graph.graphToString(tree, new NulWriter(), new LocalData()); - return tree; - } - }, timeout, TimeUnit.SECONDS); - } catch (InterruptedException ex) { - throw ex; - } catch (Exception | OutOfMemoryError | StackOverflowError ex) { - if (ex instanceof TimeoutException) { - logger.log(Level.SEVERE, "Decompilation timeout in: " + path, ex); - } else { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ex); - } - convertException = ex; - Throwable cause = ex.getCause(); - if (ex instanceof ExecutionException && cause instanceof Exception) { - convertException = cause; - } - } - writer.continueMeasure(); - - if (asm != null) { - asm.getActionSourcePrefix(writer); - } - if (convertException == null) { - Graph.graphToString(tree, writer, new LocalData()); - } else if (convertException instanceof TimeoutException) { - Helper.appendTimeoutComment(writer, timeout); - } else { - Helper.appendErrorComment(writer, convertException); - } - if (asm != null) { - asm.getActionSourceSuffix(writer); - } - } - - /** - * Converts list of actions to List of treeItems - * - * @param regNames Register names - * @param variables - * @param functions - * @param actions List of actions - * @param version SWF version - * @param staticOperation - * @param path - * @return List of treeItems - * @throws java.lang.InterruptedException - */ - public static List actionsToTree(HashMap regNames, HashMap variables, HashMap functions, List actions, int version, int staticOperation, String path) throws InterruptedException { - return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path); - } - - @Override - public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException { - ActionLocalData aLocalData = (ActionLocalData) localData; - translate(stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path); - } - - @Override - public boolean isJump() { - return false; - } - - @Override - public boolean isBranch() { - return false; - } - - @Override - public boolean isExit() { - return false; - } - - @Override - public long getOffset() { - return getAddress(); - } - - @Override - public List getBranches(GraphSource code) { - return new ArrayList<>(); - } - - @Override - public boolean isIgnored() { - return ignored; - } - - @Override - public void setIgnored(boolean ignored, int pos) { - this.ignored = ignored; - } - - private static class Loop { - - public long loopContinue; - - public long loopBreak; - - public int continueCount = 0; - - public int breakCount = 0; - - public Loop(long loopContinue, long loopBreak) { - this.loopContinue = loopContinue; - this.loopBreak = loopBreak; - } - - @Override - public String toString() { - return "[Loop continue:" + loopContinue + ", break:" + loopBreak + "]"; - } - } - - private static void log(String s) { - logger.fine(s); - } - - public static List actionsPartToTree(HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException { - if (start < actions.size() && (end > 0) && (start > 0)) { - log("Entering " + start + "-" + end + (actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : "")); - } - ActionLocalData localData = new ActionLocalData(registerNames, variables, functions); - List output = new ArrayList<>(); - int ip = start; - boolean isWhile = false; - boolean isForIn = false; - GraphTargetItem inItem = null; - int loopStart = 0; - loopip: - while (ip <= end) { - - long addr = ip2adr(actions, ip); - if (ip > end) { - break; - } - if (ip >= actions.size()) { - output.add(new ScriptEndItem()); - break; - } - Action action = actions.get(ip); - if (action.isIgnored()) { - ip++; - continue; - } - if (action instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; - //List out=actionsPartToTree(new HashMap(), new HashMap(),new HashMap(), new TranslateStack(), src, ip+1,endip-1 , version); - long endAddr = action.getAddress() + cnt.getHeaderSize(); - String cntName = cnt.getName(); - List> outs = new ArrayList<>(); - HashMap variables2 = Helper.deepCopy(variables); - if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) { - for (int r = 0; r < 256; r++) { - if (variables2.containsKey("__register" + r)) { - variables2.remove("__register" + r); - } - } - } - for (long size : cnt.getContainerSizes()) { - if (size == 0) { - outs.add(new ArrayList()); - continue; - } - List out; - try { - out = ActionGraph.translateViaGraph(cnt.getRegNames(), variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName)); - } catch (OutOfMemoryError | TranslateException | StackOverflowError ex2) { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ex2); - if (ex2 instanceof OutOfMemoryError) { - Helper.freeMem(); - } - out = new ArrayList<>(); - out.add(new CommentItem(new String[]{ - "", - " * " + AppResources.translate("decompilationError"), - " * " + AppResources.translate("decompilationError.obfuscated"), - Helper.decompilationErrorAdd == null ? null : " * " + Helper.decompilationErrorAdd, - " * " + AppResources.translate("decompilationError.errorType") + ": " - + ex2.getClass().getSimpleName(), - ""})); - } - outs.add(out); - endAddr += size; - } - ((GraphSourceItemContainer) action).translateContainer(outs, stack, output, registerNames, variables, functions); - ip = adr2ip(actions, endAddr); - continue; - } - - //return in for..in - if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { - if (ip + 3 <= end) { - if ((actions.get(ip + 1) instanceof ActionEquals) || (actions.get(ip + 1) instanceof ActionEquals2)) { - if (actions.get(ip + 2) instanceof ActionNot) { - if (actions.get(ip + 3) instanceof ActionIf) { - ActionIf aif = (ActionIf) actions.get(ip + 3); - if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) { - ip += 4; - continue; - } - } - } - } - } - } - - /*ActionJump && ActionIf removed*/ - /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) { - loopStart = ip + 1; - isForIn = true; - ip += 4; - action.translate(localData, stack, output); - EnumerateActionItem en = (EnumerateActionItem) stack.peek(); - inItem = en.object; - continue; - } else*/ /*if (action instanceof ActionTry) { - ActionTry atry = (ActionTry) action; - List tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version); - ActionItem catchName; - if (atry.catchInRegisterFlag) { - catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList()); - } else { - catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList()); - } - List catchExceptions = new ArrayList(); - catchExceptions.add(catchName); - List> catchCommands = new ArrayList>(); - catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version)); - List finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version); - output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands)); - } else if (action instanceof ActionWith) { - ActionWith awith = (ActionWith) action; - List withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList() , version); //TODO:parse with actions - output.add(new WithActionItem(action, stack.pop(), withCommands)); - } else */ if (false) { - } /*if (action instanceof ActionStoreRegister) { - if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) { - action.translate(localData, stack, output); - stack.pop(); - ip++; - } else { - try { - action.translate(localData, stack, output); - } catch (Exception ex) { - // ignore - } - } - } */ /*else if (action instanceof ActionStrictEquals) { - if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) { - List caseValues = new ArrayList(); - List> caseCommands = new ArrayList>(); - caseValues.add(stack.pop()); - ActionItem switchedObject = stack.pop(); - if (output.size() > 0) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - output.remove(output.size() - 1); - } - } - int caseStart = ip + 2; - List caseBodyIps = new ArrayList(); - long defaultAddr = 0; - caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version)); - ip++; - do { - ip++; - if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) { - caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop()); - caseStart = ip + 1; - caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version)); - if (actions.get(ip + 1) instanceof ActionJump) { - defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version); - ip = adr2ip(actions, defaultAddr, version); - break; - } - } - } while (ip < end); - - for (int i = 0; i < caseBodyIps.size(); i++) { - int caseEnd = ip - 1; - if (i < caseBodyIps.size() - 1) { - caseEnd = caseBodyIps.get(i + 1) - 1; - } - caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version)); - } - output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null)); - continue; - } else { - action.translate(stack, constants, output, registerNames); - } - } */ else { - - if (action instanceof ActionStore) { - ActionStore store = (ActionStore) action; - store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize())); - ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/; - } - - try { - action.translate(localData, stack, output, staticOperation, path); - } catch (EmptyStackException ese) { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ese); - output.add(new UnsupportedActionItem(action, "Empty stack")); - } - - } - - ip++; - } - //output = checkClass(output); - log("Leaving " + start + "-" + end); - return output; - } - - public static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) { - GraphTargetItem t = ti; - if (!(t instanceof GetMemberActionItem)) { - return ti; - } - GetMemberActionItem lastMember = null; - while (((GetMemberActionItem) t).object instanceof GetMemberActionItem) { - lastMember = (GetMemberActionItem) t; - t = ((GetMemberActionItem) t).object; - } - if (((GetMemberActionItem) t).object instanceof GetVariableActionItem) { - GetVariableActionItem v = (GetVariableActionItem) ((GetMemberActionItem) t).object; - if (v.name instanceof DirectValueActionItem) { - if (((DirectValueActionItem) v.name).value instanceof String) { - if (((DirectValueActionItem) v.name).value.equals("_global")) { - GetVariableActionItem gvt = new GetVariableActionItem(null, ((GetMemberActionItem) t).memberName); - if (lastMember == null) { - return gvt; - } else { - lastMember.object = gvt; - } - } - } - } - } - return ti; - } - - public static List checkClass(List output) { - if (true) { - //return output; - } - List ret = new ArrayList<>(); - List functions = new ArrayList<>(); - List staticFunctions = new ArrayList<>(); - List> vars = new ArrayList<>(); - List> staticVars = new ArrayList<>(); - GraphTargetItem className; - GraphTargetItem extendsOp = null; - List implementsOp = new ArrayList<>(); - boolean ok = true; - int prevCount = 0; - for (GraphTargetItem t : output) { - if (t instanceof IfItem) { - IfItem it = (IfItem) t; - if (it.expression instanceof NotItem) { - NotItem nti = (NotItem) it.expression; - if ((nti.value instanceof GetMemberActionItem) || (nti.value instanceof GetVariableActionItem)) { - if (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) { - if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) { - // ignore - } else { - List parts = it.onTrue; - className = getWithoutGlobal(nti.value); - if (parts.size() >= 1) { - int ipos = 0; - while ((parts.get(ipos) instanceof IfItem) - && ((((IfItem) parts.get(ipos)).onTrue.size() == 1) && (((IfItem) parts.get(ipos)).onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ((IfItem) parts.get(ipos)).onTrue.get(0)).value instanceof NewObjectActionItem))) { - - ipos++; - } - if (parts.get(ipos) instanceof ExtendsActionItem) { - ExtendsActionItem et = (ExtendsActionItem) parts.get(ipos); - extendsOp = getWithoutGlobal(et.superclass); - ipos++; - } - if (parts.get(ipos) instanceof StoreRegisterActionItem) { - StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); - int instanceReg = sr.register.number; - if (sr.value instanceof GetMemberActionItem) { - GetMemberActionItem gm = (GetMemberActionItem) sr.value; - //gm.memberName should be "prototype" - if (gm.object instanceof TemporaryRegister) { - TemporaryRegister tm = (TemporaryRegister) gm.object; - int classReg = tm.getRegId(); - if (tm.value instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) tm.value; - if (sm.value instanceof StoreRegisterActionItem) { - sr = (StoreRegisterActionItem) sm.value; - if (sr.value instanceof FunctionActionItem) { - ((FunctionActionItem) (sr.value)).calculatedFunctionName = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; - functions.add((FunctionActionItem) sr.value); - - for (; ipos < parts.size(); ipos++) { - if (parts.get(ipos) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); - implementsOp = io.superclasses; - continue; - } - if (parts.get(ipos) instanceof SetMemberActionItem) { - sm = (SetMemberActionItem) parts.get(ipos); - int rnum = -1; - if (sm.object instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) sm.object; - if (dv.value instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) dv.value; - rnum = rn.number; - } - } - if (sm.object instanceof TemporaryRegister) { - rnum = ((TemporaryRegister) sm.object).getRegId(); - } - if (rnum == instanceReg) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - functions.add((FunctionActionItem) sm.value); - } else { - vars.add(new MyEntry<>(sm.objectName, sm.value)); - } - } else if (rnum == classReg) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - staticFunctions.add((FunctionActionItem) sm.value); - } else { - staticVars.add(new MyEntry<>(sm.objectName, sm.value)); - } - } - - } - } - - } - - } - } - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars)); - return output2; - } - } - } else if (parts.get(ipos) instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) parts.get(0); - if (sm.value instanceof FunctionActionItem) { - FunctionActionItem f = (FunctionActionItem) sm.value; - if (f.actions.isEmpty()) { - if (parts.size() == 2) { - if (parts.get(1) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem iot = (ImplementsOpActionItem) parts.get(1); - implementsOp = iot.superclasses; - } else { - ok = false; - break; - } - } - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new InterfaceActionItem(sm.objectName, implementsOp)); - return output2; - } - } - } - } - } - } else { - ok = false; - } - } else { - ok = false; - } - } else { - ok = false; - } - } else { - prevCount++; - //ok = false; - } - if (!ok) { - break; - } - } - return output; - } - - @Override - public boolean ignoredLoops() { - return false; - } - - public static void setConstantPool(List actions, ConstantPool cpool) { - for (GraphSourceItem a : actions) { - if (a instanceof ActionPush) { - if (cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } - } - if (a instanceof ActionDefineFunction) { - if (cpool != null) { - //((ActionDefineFunction) a).setConstantPool(cpool.constants,actions); - } - } - if (a instanceof ActionDefineFunction2) { - if (cpool != null) { - //((ActionDefineFunction2) a).setConstantPool(cpool.constants,actions); - } - } - } - } - - public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { - writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode)); - return writer; - } - - public static double toFloatPoint(Object o) { - if (o instanceof Double) { - return (Double) o; - } - if (o instanceof Integer) { - return (Integer) o; - } - if (o instanceof Long) { - return (Long) o; - } - if (o instanceof String) { - try { - return Double.parseDouble((String) o); - } catch (NumberFormatException nfe) { - return 0; - } - } - return 0; - } - - public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List variables) { - GraphTargetItem ret = get; - boolean boxed = false; - if (get instanceof VariableActionItem) { - boxed = true; - ret = ((VariableActionItem) ret).getBoxedValue(); - } - if (ret instanceof GetVariableActionItem) { - GetVariableActionItem gv = (GetVariableActionItem) ret; - ret = new SetVariableActionItem(null, gv.name, value); - } else if (ret instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) ret; - ret = new SetMemberActionItem(null, mem.object, mem.memberName, value); - } else if ((ret instanceof DirectValueActionItem) && ((DirectValueActionItem) ret).value instanceof RegisterNumber) { - ret = new StoreRegisterActionItem(null, (RegisterNumber) ((DirectValueActionItem) ret).value, value, false); - } else if (ret instanceof GetPropertyActionItem) { - GetPropertyActionItem gp = (GetPropertyActionItem) ret; - ret = new SetPropertyActionItem(null, gp.target, gp.propertyIndex, value); - } - if (boxed) { - GraphTargetItem b = ret; - ret = new VariableActionItem(((VariableActionItem) get).getVariableName(), value, ((VariableActionItem) get).isDefinition()); - ((VariableActionItem) ret).setBoxedValue((ActionItem) b); - variables.remove((VariableActionItem) get); - variables.add((VariableActionItem) ret); - } - return ret; - } - - @Override - public boolean isDeobfuscatePop() { - return false; - } - - @Override - public int getLine() { - return 0; - } - - @Override - public String getFile() { - return null; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.AppResources; +import com.jpexs.decompiler.flash.BaseLocalData; +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.action.model.ActionItem; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.ExtendsActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem; +import com.jpexs.decompiler.flash.action.model.NewObjectActionItem; +import com.jpexs.decompiler.flash.action.model.SetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.SetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; +import com.jpexs.decompiler.flash.action.model.TemporaryRegister; +import com.jpexs.decompiler.flash.action.model.UnsupportedActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; +import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; +import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; +import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionStore; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.helpers.collections.MyEntry; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.CommentItem; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.ScriptEndItem; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Represents one ACTIONRECORD, also has some static method to work with Actions + */ +public abstract class Action implements GraphSourceItem { + + private static final int INFORM_LISTENER_RESOLUTION = 100; + + private boolean ignored = false; + + /** + * Action type identifier + */ + public int actionCode; + + /** + * Length of action data + */ + public int actionLength; + + private long address; + + /** + * Names of ActionScript properties + */ + public static final String[] propertyNames = new String[]{ + "_X", + "_Y", + "_xscale", + "_yscale", + "_currentframe", + "_totalframes", + "_alpha", + "_visible", + "_width", + "_height", + "_rotation", + "_target", + "_framesloaded", + "_name", + "_droptarget", + "_url", + "_highquality", + "_focusrect", + "_soundbuftime", + "_quality", + "_xmouse", + "_ymouse" + }; + + public static final List propertyNamesList = Arrays.asList(propertyNames); + + private static final Logger logger = Logger.getLogger(Action.class.getName()); + + /** + * Constructor + * + * @param actionCode Action type identifier + * @param actionLength Length of action data + */ + public Action(int actionCode, int actionLength) { + this.actionCode = actionCode; + this.actionLength = actionLength; + } + + public Action() { + } + + /** + * Returns address of this action + * + * @return address of this action + */ + public long getAddress() { + return address; + } + + /** + * Gets all addresses which are referenced from this action and/or + * subactions + * + * @param refs list of addresses + */ + public void getRef(Set refs) { + } + + /** + * Gets all addresses which are referenced from the list of actions + * + * @param list List of actions + * @return List of addresses + */ + public static Set getActionsAllRefs(List list) { + Set ret = new HashSet<>(); + for (Action a : list) { + a.getRef(ret); + } + return ret; + } + + public int getTotalActionLength() { + return actionLength + 1 + ((actionCode >= 0x80) ? 2 : 0); + } + + /** + * Sets address of this instruction + * + * @param address Address + */ + public void setAddress(long address) { + this.address = address; + } + + /** + * Returns a string representation of the object + * + * @return a string representation of the object. + */ + @Override + public String toString() { + return "Action" + actionCode; + } + + /** + * Reads String from FlasmLexer + * + * @param lex FlasmLexer + * @return String value + * @throws IOException + * @throws ActionParseException When read object is not String + */ + protected String lexString(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_STRING) { + throw new ActionParseException("String expected", lex.yyline()); + } + return (String) symb.value; + } + + /** + * Reads Block startServer from FlasmLexer + * + * @param lex FlasmLexer + * @throws IOException + * @throws ActionParseException When read object is not Block startServer + */ + protected void lexBlockOpen(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_BLOCK_START) { + throw new ActionParseException("Block startServer ", lex.yyline()); + } + } + + /** + * Reads Identifier from FlasmLexer + * + * @param lex FlasmLexer + * @return Identifier name + * @throws IOException + * @throws ActionParseException When read object is not Identifier + */ + protected String lexIdentifier(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_IDENTIFIER) { + throw new ActionParseException("Identifier expected", lex.yyline()); + } + return (String) symb.value; + } + + /** + * Reads long value from FlasmLexer + * + * @param lex FlasmLexer + * @return long value + * @throws IOException + * @throws ActionParseException When read object is not long value + */ + protected long lexLong(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_INTEGER) { + throw new ActionParseException("Integer expected", lex.yyline()); + } + return (Long) symb.value; + } + + /** + * Reads boolean value from FlasmLexer + * + * @param lex FlasmLexer + * @return boolean value + * @throws IOException + * @throws ActionParseException When read object is not boolean value + */ + protected boolean lexBoolean(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_BOOLEAN) { + throw new ActionParseException("Boolean expected", lex.yyline()); + } + return (Boolean) symb.value; + } + + /** + * Gets action converted to bytes + * + * @param version SWF version + * @return Array of bytes + */ + public byte[] getBytes(int version) { + return surroundWithAction(new byte[0], version); + } + + /** + * Gets the length of action converted to bytes + * + * @param version SWF version + * @return Length + */ + public int getBytesLength(int version) { + return getBytes(version).length; + } + + /** + * Uptates the action length to the length calculated from action bytes + * + * @param version SWF version + */ + public void updateLength(int version) { + int length = getBytes(version).length; + actionLength = length - 1 - ((actionCode >= 0x80) ? 2 : 0); + } + + /** + * Surrounds byte array with Action header + * + * @param data Byte array + * @param version SWF version + * @return Byte array + */ + protected byte[] surroundWithAction(byte[] data, int version) { + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + SWFOutputStream sos2 = new SWFOutputStream(baos2, version); + try { + sos2.writeUI8(actionCode); + if (actionCode >= 0x80) { + sos2.writeUI16(data.length); + } + sos2.write(data); + sos2.close(); + } catch (IOException e) { + throw new Error("This should never happen.", e); + } + return baos2.toByteArray(); + } + + /** + * Converts list of Actions to bytes + * + * @param list List of actions + * @param addZero Whether or not to add 0 UI8 value to the end + * @param version SWF version + * @return Array of bytes + */ + public static byte[] actionsToBytes(List list, boolean addZero, int version) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Action lastAction = null; + for (Action a : list) { + try { + lastAction = a; + baos.write(a.getBytes(version)); + } catch (IOException e) { + } + } + if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { + baos.write(0); + } + return baos.toByteArray(); + } + + /** + * Set addresses of actions in the list + * + * @param list List of actions + * @param baseAddress Address of first action in the list + */ + public static void setActionsAddresses(List list, long baseAddress) { + long offset = baseAddress; + for (Action a : list) { + a.setAddress(offset); + offset += a.getTotalActionLength(); + } + } + + /** + * Converts list of actions to ASM source + * + * @param listeners + * @param address + * @param list List of actions + * @param version SWF version + * @param exportMode PCode or hex? + * @return source ASM + * + */ + public static String actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode) { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + actionsToString(listeners, address, list, version, exportMode, writer); + return writer.toString(); + } + + /** + * Converts list of actions to ASM source + * + * @param listeners + * @param address + * @param list List of actions + * @param version SWF version + * @param exportMode PCode or hex? + * @param writer + * @return GraphTextWriter + */ + public static GraphTextWriter actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + if (exportMode == ScriptExportMode.CONSTANTS) { + return constantPoolActionsToString(listeners, address, list, version, exportMode, writer); + } + + long offset; + Set importantOffsets = getActionsAllRefs(list); + /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); + if (!cps.isEmpty()) { + setConstantPool(list, cps.get(cps.size() - 1)); + }*/ + HashMap> containers = new HashMap<>(); + HashMap containersPos = new HashMap<>(); + offset = address; + int pos = 0; + boolean lastPush = false; + for (Action a : list) { + if (pos % INFORM_LISTENER_RESOLUTION == 0) { + for (DisassemblyListener listener : listeners) { + listener.progressToString(pos + 1, list.size()); + } + } + + if (exportMode == ScriptExportMode.PCODE_HEX) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("; "); + writer.appendNoHilight(Helper.bytesToHexString(a.getBytes(version))); + writer.newLine(); + } + + offset = a.getAddress(); + + if ((!(a.isIgnored())) && (a instanceof GraphSourceItemContainer)) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + containersPos.put(cnt, 0); + List sizes = cnt.getContainerSizes(); + long addr = ((Action) cnt).getAddress() + cnt.getHeaderSize(); + for (Long size : sizes) { + addr += size; + if (size == 0) { + continue; + } + if (!containers.containsKey(addr)) { + containers.put(addr, new ArrayList()); + } + containers.get(addr).add(cnt); + } + } + + if (containers.containsKey(offset)) { + for (int i = 0; i < containers.get(offset).size(); i++) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("}").newLine(); + GraphSourceItemContainer cnt = containers.get(offset).get(i); + int cntPos = containersPos.get(cnt); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); + cntPos++; + containersPos.put(cnt, cntPos); + } + } + + if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + } + + if (a.isIgnored()) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + if (!(a instanceof ActionEnd)) { + int len = a.getTotalActionLength(); + for (int i = 0; i < len; i++) { + writer.appendNoHilight("Nop").newLine(); + } + } + } else { + //if (!(a instanceof ActionNop)) { + String add = ""; + // honfika: commented out the following lines, because it makes no sense + /*if (a instanceof ActionIf) { + add = " change: " + ((ActionIf) a).getJumpOffset(); + } + if (a instanceof ActionJump) { + add = " change: " + ((ActionJump) a).getJumpOffset(); + } + add = "; ofs" + Helper.formatAddress(offset) + add; + add = "";*/ + if ((a instanceof ActionPush) && lastPush) { + writer.appendNoHilight(" "); + ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, exportMode, writer); + } else { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + + writer.append("", offset); + + int fixBranch = -1; + if (a instanceof ActionIf) { + ActionIf aif = (ActionIf) a; + if (aif.jumpUsed && !aif.ignoreUsed) { + fixBranch = 0; + } + if (!aif.jumpUsed && aif.ignoreUsed) { + fixBranch = 1; + } + } + + if (fixBranch > -1) { + writer.appendNoHilight("FFDec_DeobfuscatePop"); + if (fixBranch == 0) { //jump + writer.newLine(); + writer.appendNoHilight("Jump loc"); + writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getTotalActionLength() + ((ActionIf) a).getJumpOffset())); + } else { + //nojump, ignore + } + } else { + a.getASMSourceReplaced(list, importantOffsets, exportMode, writer); + } + writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); + writer.appendNoHilight(add); + if (!(a instanceof ActionPush)) { + writer.newLine(); + } + } + if (a instanceof ActionPush) { + lastPush = true; + } else { + lastPush = false; + } + //} + } + + offset += a.getTotalActionLength(); + pos++; + } + if (lastPush) { + writer.newLine(); + } + + if (containers.containsKey(offset)) { + for (int i = 0; i < containers.get(offset).size(); i++) { + writer.appendNoHilight("}"); + writer.newLine(); + GraphSourceItemContainer cnt = containers.get(offset).get(i); + int cntPos = containersPos.get(cnt); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); + cntPos++; + containersPos.put(cnt, cntPos); + } + } + + if (importantOffsets.contains(offset)) { + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + writer.newLine(); + } + + return writer; + } + + public static GraphTextWriter constantPoolActionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + int poolIdx = 0; + writer.appendNoHilight(Helper.constants).newLine(); + for (Action a : list) { + if (a instanceof ActionConstantPool) { + if (poolIdx > 0) { + writer.appendNoHilight("---").newLine(); + } + + ActionConstantPool cPool = (ActionConstantPool) a; + int constIdx = 0; + for (String c : cPool.constantPool) { + writer.appendNoHilight(constIdx); + writer.appendNoHilight("|"); + writer.appendNoHilight(Helper.escapeString(c)); + writer.newLine(); + constIdx++; + } + + poolIdx++; + } + } + + return writer; + } + + /** + * Convert action to ASM source + * + * @param container + * @param knownAddreses List of important offsets to mark as labels + * @param exportMode PCode or hex? + * @return String of P-code source + */ + public String getASMSource(ActionList container, Set knownAddreses, ScriptExportMode exportMode) { + return toString(); + } + + /** + * Translates this function to stack and output. + * + * @param stack Stack + * @param output Output + * @param regNames Register names + * @param variables Variables + * @param functions Functions + * @param staticOperation the value of staticOperation + * @param path the value of path + * @throws java.lang.InterruptedException + */ + public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) throws InterruptedException { + } + + /** + * Pops long value off the stack + * + * @param stack Stack + * @return long value + */ + protected long popLong(TranslateStack stack) { + GraphTargetItem item = stack.pop(); + if (item instanceof DirectValueActionItem) { + if (((DirectValueActionItem) item).value instanceof Long) { + return (long) (Long) ((DirectValueActionItem) item).value; + } + } + return 0; + } + + /** + * Converts action index to address in the specified list of actions + * + * @param actions List of actions + * @param ip Action index + * @return address + */ + public static long ip2adr(List actions, int ip) { + /* List actions=new ArrayList(); + for(GraphSourceItem s:sources){ + if(s instanceof Action){ + actions.add((Action)s); + } + }*/ + if (ip >= actions.size()) { + if (actions.isEmpty()) { + return 0; + } + return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); + } + if (ip == -1) { + return 0; + } + return actions.get(ip).getAddress(); + } + + /** + * Converts address to action index in the specified list of actions + * + * @param actions List of actions + * @param addr Address + * @return action index + */ + public static int adr2ip(List actions, long addr) { + for (int ip = 0; ip < actions.size(); ip++) { + if (actions.get(ip).getAddress() == addr) { + return ip; + } + } + if (actions.size() > 0) { + long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); + if (addr == outpos) { + return actions.size(); + } + } + return -1; + } + + public static List actionsToTree(List actions, int version, int staticOperation, String path) throws InterruptedException { + return actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); + } + + /** + * Converts list of actions to ActionScript source code + * + * @param asm + * @param actions List of actions + * @param path + * @return source + * @throws java.lang.InterruptedException + */ + public static String actionsToSource(final ASMSource asm, final List actions, final String path) throws InterruptedException { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + actionsToSource(asm, actions, path, writer); + return writer.toString(); + } + + /** + * Converts list of actions to ActionScript source code + * + * @param asm + * @param actions List of actions + * @param path + * @param writer + * @throws java.lang.InterruptedException + */ + public static void actionsToSource(final ASMSource asm, final List actions, final String path, GraphTextWriter writer) throws InterruptedException { + writer.suspendMeasure(); + List tree = null; + Throwable convertException = null; + int timeout = Configuration.decompilationTimeoutSingleMethod.get(); + final int version = asm == null ? SWF.DEFAULT_VERSION : asm.getSwf().version; + try { + tree = CancellableWorker.call(new Callable>() { + @Override + public List call() throws Exception { + 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); + Graph.graphToString(tree, new NulWriter(), new LocalData()); + return tree; + } + }, timeout, TimeUnit.SECONDS); + } catch (InterruptedException ex) { + throw ex; + } catch (Exception | OutOfMemoryError | StackOverflowError ex) { + if (ex instanceof TimeoutException) { + logger.log(Level.SEVERE, "Decompilation timeout in: " + path, ex); + } else { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ex); + } + convertException = ex; + Throwable cause = ex.getCause(); + if (ex instanceof ExecutionException && cause instanceof Exception) { + convertException = cause; + } + } + writer.continueMeasure(); + + if (asm != null) { + asm.getActionSourcePrefix(writer); + } + if (convertException == null) { + Graph.graphToString(tree, writer, new LocalData()); + } else if (convertException instanceof TimeoutException) { + Helper.appendTimeoutComment(writer, timeout); + } else { + Helper.appendErrorComment(writer, convertException); + } + if (asm != null) { + asm.getActionSourceSuffix(writer); + } + } + + /** + * Converts list of actions to List of treeItems + * + * @param regNames Register names + * @param variables + * @param functions + * @param actions List of actions + * @param version SWF version + * @param staticOperation + * @param path + * @return List of treeItems + * @throws java.lang.InterruptedException + */ + public static List actionsToTree(HashMap regNames, HashMap variables, HashMap functions, List actions, int version, int staticOperation, String path) throws InterruptedException { + return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path); + } + + @Override + public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException { + ActionLocalData aLocalData = (ActionLocalData) localData; + translate(stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path); + } + + @Override + public boolean isJump() { + return false; + } + + @Override + public boolean isBranch() { + return false; + } + + @Override + public boolean isExit() { + return false; + } + + @Override + public long getOffset() { + return getAddress(); + } + + @Override + public List getBranches(GraphSource code) { + return new ArrayList<>(); + } + + @Override + public boolean isIgnored() { + return ignored; + } + + @Override + public void setIgnored(boolean ignored, int pos) { + this.ignored = ignored; + } + + private static class Loop { + + public long loopContinue; + + public long loopBreak; + + public int continueCount = 0; + + public int breakCount = 0; + + public Loop(long loopContinue, long loopBreak) { + this.loopContinue = loopContinue; + this.loopBreak = loopBreak; + } + + @Override + public String toString() { + return "[Loop continue:" + loopContinue + ", break:" + loopBreak + "]"; + } + } + + private static void log(String s) { + logger.fine(s); + } + + public static List actionsPartToTree(HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException { + if (start < actions.size() && (end > 0) && (start > 0)) { + log("Entering " + start + "-" + end + (actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : "")); + } + ActionLocalData localData = new ActionLocalData(registerNames, variables, functions); + List output = new ArrayList<>(); + int ip = start; + boolean isWhile = false; + boolean isForIn = false; + GraphTargetItem inItem = null; + int loopStart = 0; + loopip: + while (ip <= end) { + + long addr = ip2adr(actions, ip); + if (ip > end) { + break; + } + if (ip >= actions.size()) { + output.add(new ScriptEndItem()); + break; + } + Action action = actions.get(ip); + if (action.isIgnored()) { + ip++; + continue; + } + if (action instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; + //List out=actionsPartToTree(new HashMap(), new HashMap(),new HashMap(), new TranslateStack(), src, ip+1,endip-1 , version); + long endAddr = action.getAddress() + cnt.getHeaderSize(); + String cntName = cnt.getName(); + List> outs = new ArrayList<>(); + HashMap variables2 = Helper.deepCopy(variables); + if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) { + for (int r = 0; r < 256; r++) { + if (variables2.containsKey("__register" + r)) { + variables2.remove("__register" + r); + } + } + } + for (long size : cnt.getContainerSizes()) { + if (size == 0) { + outs.add(new ArrayList()); + continue; + } + List out; + try { + out = ActionGraph.translateViaGraph(cnt.getRegNames(), variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName)); + } catch (OutOfMemoryError | TranslateException | StackOverflowError ex2) { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ex2); + if (ex2 instanceof OutOfMemoryError) { + Helper.freeMem(); + } + out = new ArrayList<>(); + out.add(new CommentItem(new String[]{ + "", + " * " + AppResources.translate("decompilationError"), + " * " + AppResources.translate("decompilationError.obfuscated"), + Helper.decompilationErrorAdd == null ? null : " * " + Helper.decompilationErrorAdd, + " * " + AppResources.translate("decompilationError.errorType") + ": " + + ex2.getClass().getSimpleName(), + ""})); + } + outs.add(out); + endAddr += size; + } + ((GraphSourceItemContainer) action).translateContainer(outs, stack, output, registerNames, variables, functions); + ip = adr2ip(actions, endAddr); + continue; + } + + //return in for..in + if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { + if (ip + 3 <= end) { + if ((actions.get(ip + 1) instanceof ActionEquals) || (actions.get(ip + 1) instanceof ActionEquals2)) { + if (actions.get(ip + 2) instanceof ActionNot) { + if (actions.get(ip + 3) instanceof ActionIf) { + ActionIf aif = (ActionIf) actions.get(ip + 3); + if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) { + ip += 4; + continue; + } + } + } + } + } + } + + /*ActionJump && ActionIf removed*/ + /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) { + loopStart = ip + 1; + isForIn = true; + ip += 4; + action.translate(localData, stack, output); + EnumerateActionItem en = (EnumerateActionItem) stack.peek(); + inItem = en.object; + continue; + } else*/ /*if (action instanceof ActionTry) { + ActionTry atry = (ActionTry) action; + List tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version); + ActionItem catchName; + if (atry.catchInRegisterFlag) { + catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList()); + } else { + catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList()); + } + List catchExceptions = new ArrayList(); + catchExceptions.add(catchName); + List> catchCommands = new ArrayList>(); + catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version)); + List finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version); + output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands)); + } else if (action instanceof ActionWith) { + ActionWith awith = (ActionWith) action; + List withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList() , version); //TODO:parse with actions + output.add(new WithActionItem(action, stack.pop(), withCommands)); + } else */ if (false) { + } /*if (action instanceof ActionStoreRegister) { + if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) { + action.translate(localData, stack, output); + stack.pop(); + ip++; + } else { + try { + action.translate(localData, stack, output); + } catch (Exception ex) { + // ignore + } + } + } */ /*else if (action instanceof ActionStrictEquals) { + if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) { + List caseValues = new ArrayList(); + List> caseCommands = new ArrayList>(); + caseValues.add(stack.pop()); + ActionItem switchedObject = stack.pop(); + if (output.size() > 0) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + output.remove(output.size() - 1); + } + } + int caseStart = ip + 2; + List caseBodyIps = new ArrayList(); + long defaultAddr = 0; + caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version)); + ip++; + do { + ip++; + if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) { + caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop()); + caseStart = ip + 1; + caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version)); + if (actions.get(ip + 1) instanceof ActionJump) { + defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version); + ip = adr2ip(actions, defaultAddr, version); + break; + } + } + } while (ip < end); + + for (int i = 0; i < caseBodyIps.size(); i++) { + int caseEnd = ip - 1; + if (i < caseBodyIps.size() - 1) { + caseEnd = caseBodyIps.get(i + 1) - 1; + } + caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version)); + } + output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null)); + continue; + } else { + action.translate(stack, constants, output, registerNames); + } + } */ else { + + if (action instanceof ActionStore) { + ActionStore store = (ActionStore) action; + store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize())); + ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/; + } + + try { + action.translate(localData, stack, output, staticOperation, path); + } catch (EmptyStackException ese) { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ese); + output.add(new UnsupportedActionItem(action, "Empty stack")); + } + + } + + ip++; + } + //output = checkClass(output); + log("Leaving " + start + "-" + end); + return output; + } + + public static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) { + GraphTargetItem t = ti; + if (!(t instanceof GetMemberActionItem)) { + return ti; + } + GetMemberActionItem lastMember = null; + while (((GetMemberActionItem) t).object instanceof GetMemberActionItem) { + lastMember = (GetMemberActionItem) t; + t = ((GetMemberActionItem) t).object; + } + if (((GetMemberActionItem) t).object instanceof GetVariableActionItem) { + GetVariableActionItem v = (GetVariableActionItem) ((GetMemberActionItem) t).object; + if (v.name instanceof DirectValueActionItem) { + if (((DirectValueActionItem) v.name).value instanceof String) { + if (((DirectValueActionItem) v.name).value.equals("_global")) { + GetVariableActionItem gvt = new GetVariableActionItem(null, ((GetMemberActionItem) t).memberName); + if (lastMember == null) { + return gvt; + } else { + lastMember.object = gvt; + } + } + } + } + } + return ti; + } + + public static List checkClass(List output) { + if (true) { + //return output; + } + List ret = new ArrayList<>(); + List functions = new ArrayList<>(); + List staticFunctions = new ArrayList<>(); + List> vars = new ArrayList<>(); + List> staticVars = new ArrayList<>(); + GraphTargetItem className; + GraphTargetItem extendsOp = null; + List implementsOp = new ArrayList<>(); + boolean ok = true; + int prevCount = 0; + for (GraphTargetItem t : output) { + if (t instanceof IfItem) { + IfItem it = (IfItem) t; + if (it.expression instanceof NotItem) { + NotItem nti = (NotItem) it.expression; + if ((nti.value instanceof GetMemberActionItem) || (nti.value instanceof GetVariableActionItem)) { + if (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) { + if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) { + // ignore + } else { + List parts = it.onTrue; + className = getWithoutGlobal(nti.value); + if (parts.size() >= 1) { + int ipos = 0; + while ((parts.get(ipos) instanceof PopItem) || ((parts.get(ipos) instanceof IfItem) + && ((((IfItem) parts.get(ipos)).onTrue.size() == 1) && (((IfItem) parts.get(ipos)).onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ((IfItem) parts.get(ipos)).onTrue.get(0)).value instanceof NewObjectActionItem)))) { + + ipos++; + } + if (parts.get(ipos) instanceof ExtendsActionItem) { + ExtendsActionItem et = (ExtendsActionItem) parts.get(ipos); + extendsOp = getWithoutGlobal(et.superclass); + ipos++; + } + if (parts.get(ipos) instanceof StoreRegisterActionItem) { + StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); + int instanceReg = sr.register.number; + if (sr.value instanceof GetMemberActionItem) { + GetMemberActionItem gm = (GetMemberActionItem) sr.value; + //gm.memberName should be "prototype" + if (gm.object instanceof TemporaryRegister) { + TemporaryRegister tm = (TemporaryRegister) gm.object; + int classReg = tm.getRegId(); + if (tm.value instanceof SetMemberActionItem) { + SetMemberActionItem sm = (SetMemberActionItem) tm.value; + if (sm.value instanceof StoreRegisterActionItem) { + sr = (StoreRegisterActionItem) sm.value; + if (sr.value instanceof FunctionActionItem) { + ((FunctionActionItem) (sr.value)).calculatedFunctionName = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; + functions.add((FunctionActionItem) sr.value); + + for (; ipos < parts.size(); ipos++) { + if (parts.get(ipos) instanceof ImplementsOpActionItem) { + ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); + implementsOp = io.superclasses; + continue; + } + if (parts.get(ipos) instanceof SetMemberActionItem) { + sm = (SetMemberActionItem) parts.get(ipos); + int rnum = -1; + if (sm.object instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) sm.object; + if (dv.value instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) dv.value; + rnum = rn.number; + } + } + if (sm.object instanceof TemporaryRegister) { + rnum = ((TemporaryRegister) sm.object).getRegId(); + } + if (rnum == instanceReg) { + if (sm.value instanceof FunctionActionItem) { + ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; + functions.add((FunctionActionItem) sm.value); + } else { + vars.add(new MyEntry<>(sm.objectName, sm.value)); + } + } else if (rnum == classReg) { + if (sm.value instanceof FunctionActionItem) { + ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; + staticFunctions.add((FunctionActionItem) sm.value); + } else { + staticVars.add(new MyEntry<>(sm.objectName, sm.value)); + } + } + + } + } + + } + + } + } + List output2 = new ArrayList<>(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars)); + return output2; + } + } + } else if (parts.get(ipos) instanceof SetMemberActionItem) { + SetMemberActionItem sm = (SetMemberActionItem) parts.get(0); + if (sm.value instanceof FunctionActionItem) { + FunctionActionItem f = (FunctionActionItem) sm.value; + if (f.actions.isEmpty()) { + if (parts.size() == 2) { + if (parts.get(1) instanceof ImplementsOpActionItem) { + ImplementsOpActionItem iot = (ImplementsOpActionItem) parts.get(1); + implementsOp = iot.superclasses; + } else { + ok = false; + break; + } + } + List output2 = new ArrayList<>(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new InterfaceActionItem(sm.objectName, implementsOp)); + return output2; + } + } + } + } + } + } else { + ok = false; + } + } else { + ok = false; + } + } else { + ok = false; + } + } else if (!(t instanceof PopItem)) { + prevCount++; + //ok = false; + } + if (!ok) { + break; + } + } + return output; + } + + @Override + public boolean ignoredLoops() { + return false; + } + + public static void setConstantPool(List actions, ConstantPool cpool) { + for (GraphSourceItem a : actions) { + if (a instanceof ActionPush) { + if (cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } + } + if (a instanceof ActionDefineFunction) { + if (cpool != null) { + //((ActionDefineFunction) a).setConstantPool(cpool.constants,actions); + } + } + if (a instanceof ActionDefineFunction2) { + if (cpool != null) { + //((ActionDefineFunction2) a).setConstantPool(cpool.constants,actions); + } + } + } + } + + public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { + writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode)); + return writer; + } + + public static double toFloatPoint(Object o) { + if (o instanceof Double) { + return (Double) o; + } + if (o instanceof Integer) { + return (Integer) o; + } + if (o instanceof Long) { + return (Long) o; + } + if (o instanceof String) { + try { + return Double.parseDouble((String) o); + } catch (NumberFormatException nfe) { + return 0; + } + } + return 0; + } + + public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List variables) { + GraphTargetItem ret = get; + boolean boxed = false; + if (get instanceof VariableActionItem) { + boxed = true; + ret = ((VariableActionItem) ret).getBoxedValue(); + } + if (ret instanceof GetVariableActionItem) { + GetVariableActionItem gv = (GetVariableActionItem) ret; + ret = new SetVariableActionItem(null, gv.name, value); + } else if (ret instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) ret; + ret = new SetMemberActionItem(null, mem.object, mem.memberName, value); + } else if ((ret instanceof DirectValueActionItem) && ((DirectValueActionItem) ret).value instanceof RegisterNumber) { + ret = new StoreRegisterActionItem(null, (RegisterNumber) ((DirectValueActionItem) ret).value, value, false); + } else if (ret instanceof GetPropertyActionItem) { + GetPropertyActionItem gp = (GetPropertyActionItem) ret; + ret = new SetPropertyActionItem(null, gp.target, gp.propertyIndex, value); + } + if (boxed) { + GraphTargetItem b = ret; + ret = new VariableActionItem(((VariableActionItem) get).getVariableName(), value, ((VariableActionItem) get).isDefinition()); + ((VariableActionItem) ret).setBoxedValue((ActionItem) b); + variables.remove((VariableActionItem) get); + variables.add((VariableActionItem) ret); + } + return ret; + } + + @Override + public boolean isDeobfuscatePop() { + return false; + } + + @Override + public int getLine() { + return 0; + } + + @Override + public String getFile() { + return null; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java index f0cda222a..599018dc0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -1,487 +1,487 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action; - -import com.jpexs.decompiler.flash.BaseLocalData; -import com.jpexs.decompiler.flash.FinalProcessLocalData; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; -import com.jpexs.decompiler.flash.action.model.FunctionActionItem; -import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem; -import com.jpexs.decompiler.flash.action.model.SetTargetActionItem; -import com.jpexs.decompiler.flash.action.model.SetTypeActionItem; -import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem; -import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem; -import com.jpexs.decompiler.flash.action.model.operations.StrictEqActionItem; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSource; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.Loop; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.BreakItem; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.SwitchItem; -import com.jpexs.decompiler.graph.model.WhileItem; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class ActionGraph extends Graph { - - public ActionGraph(List code, HashMap registerNames, HashMap variables, HashMap functions, int version) { - super(new ActionGraphSource(code, version, registerNames, variables, functions), new ArrayList()); - //this.version = version; - /*heads = makeGraph(code, new ArrayList()); - for (GraphPart head : heads) { - fixGraph(head); - makeMulti(head, new ArrayList()); - }*/ - } - - public static List translateViaGraph(HashMap registerNames, HashMap variables, HashMap functions, List code, int version, int staticOperation, String path) throws InterruptedException { - - ActionGraph g = new ActionGraph(code, registerNames, variables, functions, version); - ActionLocalData localData = new ActionLocalData(registerNames); - g.init(localData); - return g.translate(localData, staticOperation, path); - } - - @Override - public void finalProcessStack(TranslateStack stack, List output) { - if (stack.size() > 0) { - for (int i = stack.size() - 1; i >= 0; i--) { - //System.err.println(stack.get(i)); - if (stack.get(i) instanceof FunctionActionItem) { - FunctionActionItem f = (FunctionActionItem) stack.remove(i); - if (!output.contains(f)) { - output.add(0, f); - } - } - } - } - } - - @Override - protected void finalProcess(List list, int level, FinalProcessLocalData localData) { - super.finalProcess(list, level, localData); - List ret = Action.checkClass(list); - if (ret != list) { - list.clear(); - list.addAll(ret); - } - int targetStart; - int targetEnd; - - boolean again; - do { - again = false; - targetStart = -1; - targetEnd = -1; - GraphTargetItem targetStartItem = null; - GraphTargetItem target = null; - for (int t = 0; t < list.size(); t++) { - GraphTargetItem it = list.get(t); - if (it instanceof SetTargetActionItem) { - SetTargetActionItem st = (SetTargetActionItem) it; - if (st.target.isEmpty()) { - if (targetStart > -1) { - targetEnd = t; - break; - } - } else { - target = new DirectValueActionItem(null, 0, st.target, new ArrayList()); - targetStart = t; - targetStartItem = it; - } - } - if (it instanceof SetTarget2ActionItem) { - SetTarget2ActionItem st = (SetTarget2ActionItem) it; - if ((st.target instanceof DirectValueActionItem) && st.target.getResult().equals("")) { - if (targetStart > -1) { - targetEnd = t; - break; - } - } else { - targetStart = t; - target = st.target; - targetStartItem = it; - } - } - } - if ((targetStart > -1) && (targetEnd > -1)) { - List newlist = new ArrayList<>(); - for (int i = 0; i < targetStart; i++) { - newlist.add(list.get(i)); - } - List tellist = new ArrayList<>(); - for (int i = targetStart + 1; i < targetEnd; i++) { - tellist.add(list.get(i)); - } - newlist.add(new TellTargetActionItem(targetStartItem.src, target, tellist)); - for (int i = targetEnd + 1; i < list.size(); i++) { - newlist.add(list.get(i)); - } - list.clear(); - list.addAll(newlist); - again = true; - } - } while (again); - for (int t = 0; t < list.size(); t++) { - GraphTargetItem it = list.get(t); - - if (it instanceof WhileItem) { - WhileItem wi = (WhileItem) it; - if ((!wi.commands.isEmpty()) && (wi.commands.get(0) instanceof SetTypeActionItem)) { - SetTypeActionItem sti = (SetTypeActionItem) wi.commands.get(0); - if (wi.expression.get(wi.expression.size() - 1) instanceof NeqActionItem) { - NeqActionItem ne = (NeqActionItem) wi.expression.get(wi.expression.size() - 1); - if (ne.rightSide instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide; - if (dv.value instanceof Null) { - GraphTargetItem en = ne.leftSide; - if (en instanceof StoreRegisterActionItem) { - en = ((StoreRegisterActionItem) en).value; - } - if (en instanceof EnumerateActionItem) { - EnumerateActionItem eti = (EnumerateActionItem) en; - list.remove(t); - wi.commands.remove(0); - list.add(t, new ForInActionItem(null, wi.loop, sti.getObject(), eti.object, wi.commands)); - } - } - } - } - } - - } - } - //detectChained(list, temporaryRegisters); - } - - @Override - protected List checkPrecoNextParts(GraphPart part) { - List items = getPartItems(part); - part = makeMultiPart(part); - if (items.size() > 1) { - if (items.get(items.size() - 1) instanceof ActionIf) { - if (items.get(items.size() - 2) instanceof ActionStrictEquals) { - List storeRegisters = new ArrayList<>(); - for (GraphSourceItem s : items) { - if (s instanceof ActionStoreRegister) { - ActionStoreRegister sr = (ActionStoreRegister) s; - storeRegisters.add(sr.registerNumber); - } - } - if (!storeRegisters.isEmpty()) { - List caseBodies = new ArrayList<>(); - boolean proceed = false; - do { - proceed = false; - caseBodies.add(part.nextParts.get(0)); //jump - part = part.nextParts.get(1); //nojump - items = getPartItems(part); - part = makeMultiPart(part); - if (!items.isEmpty()) { - if (items.get(0) instanceof ActionPush) { - ActionPush pu = (ActionPush) items.get(0); - if (!pu.values.isEmpty()) { - if (pu.values.get(0) instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) pu.values.get(0); - if (storeRegisters.contains(rn.number)) { - storeRegisters.clear(); - storeRegisters.add(rn.number); - if (items.get(items.size() - 1) instanceof ActionIf) { - if (items.size() > 1) { - if (items.get(items.size() - 2) instanceof ActionStrictEquals) { - proceed = true; - } - } - } - } - } - } - } - } - } while (proceed); - - if (caseBodies.size() > 1) { - caseBodies.add(part); //TODO: properly detect default clause (?) - return caseBodies; - } - } - } - } - } - return null; - } - - @Override - protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - StoreRegisterActionItem str = (StoreRegisterActionItem) output.get(output.size() - 1); - if (str.value instanceof EnumerateActionItem) { - output.remove(output.size() - 1); - } - } - } - List ret = null; - if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && (stack.peek() instanceof StrictEqActionItem)) { - - GraphTargetItem switchedObject = null; - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - switchedObject = ((StoreRegisterActionItem) output.get(output.size() - 1)).value; - } - } - if (switchedObject == null) { - switchedObject = new DirectValueActionItem(null, -1, new Null(), null); - } - HashMap caseValuesMap = new HashMap<>(); - - int pos = 0; - StrictEqActionItem set = (StrictEqActionItem) stack.pop(); - caseValuesMap.put(pos, set.rightSide); - if (set.leftSide instanceof StoreRegisterActionItem) { - switchedObject = ((StoreRegisterActionItem) set.leftSide).value; - } - //GraphPart switchLoc = part.nextParts.get(1).nextParts.get(0); - List caseBodyParts = new ArrayList<>(); - caseBodyParts.add(part.nextParts.get(0)); - GraphTargetItem top = null; - int cnt = 1; - while (part.nextParts.size() > 1 - && part.nextParts.get(1).getHeight() > 1 - && code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end) instanceof ActionIf - && ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) { - cnt++; - part = part.nextParts.get(1); - pos++; - caseBodyParts.add(part.nextParts.get(0)); - - set = (StrictEqActionItem) top; - caseValuesMap.put(pos, set.rightSide); - } - if (cnt == 1) { - stack.push(set); - } else { - part = part.nextParts.get(1); - - GraphPart defaultPart = part; //21-21 - //caseBodyParts.add(defaultPart); - - List defaultAndLastPart = new ArrayList<>(); - defaultAndLastPart.add(defaultPart); - defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1)); - - GraphPart defaultPart2 = getCommonPart(localData, defaultAndLastPart, loops);//34-37 - - List defaultCommands = new ArrayList<>(); - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(defaultPart2); - defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path); - - List loopContinues = new ArrayList<>(); - for (Loop l : loops) { - if (l.loopContinue != null) { - loopContinues.add(l.loopContinue); - } - } - - List breakParts = new ArrayList<>(); - /*for (int g = 0; g < caseBodyParts.size(); g++) { - if (g < caseBodyParts.size() - 1) { - if (caseBodyParts.get(g).leadsTo(code, caseBodyParts.get(g + 1), loops)) { - continue; - } - } - GraphPart nsp = caseBodyParts.get(g).getNextSuperPartPath(loopContinues); - if (nsp != null) { - breakParts.add(nsp); - } - } - Collections.sort(breakParts, new Comparator() { - @Override - public int compare(GraphPart o1, GraphPart o2) { - return o2.path.length() - o1.path.length(); - } - });*/ - - //GraphPart breakPart = breakParts.isEmpty() ? null : breakParts.get(0); - List mcp = new ArrayList<>(); - mcp.addAll(caseBodyParts); - if (defaultPart2 != null) { - mcp.add(defaultPart2); - } - GraphPart breakPart = getMostCommonPart(localData, mcp, loops); - if ((defaultPart2 != breakPart) && (defaultCommands.isEmpty())) { - defaultPart = defaultPart2; - } - - List caseValues = new ArrayList<>(); - for (int i = 0; i < caseBodyParts.size(); i++) { - if (caseValuesMap.containsKey(i)) { - caseValues.add(caseValuesMap.get(i)); - } else { - continue; - } - } - - List> caseCommands = new ArrayList<>(); - GraphPart next = null; - - next = breakPart; - - GraphTargetItem ti = checkLoop(next, stopPart, loops); - currentLoop = new Loop(loops.size(), null, next); - currentLoop.phase = 1; - loops.add(currentLoop); - //switchLoc.getNextPartPath(new ArrayList()); - List valuesMapping = new ArrayList<>(); - List caseBodies = new ArrayList<>(); - for (int i = 0; i < caseValues.size(); i++) { - GraphPart cur = caseBodyParts.get(i); - if (!caseBodies.contains(cur)) { - caseBodies.add(cur); - } - valuesMapping.add(caseBodies.indexOf(cur)); - } - - if (defaultPart == breakPart) { - defaultPart = null; - } - if ((defaultPart != null) && (defaultCommands.isEmpty())) { - List stopPart2x = new ArrayList<>(stopPart); - stopPart2x.add(next); - defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path); - } - - if (!defaultCommands.isEmpty()) { - if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) { - BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1); - if (bi.loopId == currentLoop.id) { - defaultCommands.remove(defaultCommands.size() - 1); - } - } - } - - List ignored = new ArrayList<>(); - for (Loop l : loops) { - ignored.add(l.loopContinue); - } - - for (int i = 0; i < caseBodies.size(); i++) { - List cc = new ArrayList<>(); - GraphPart nextCase = null; - nextCase = next; - if (next != null) { - if (i < caseBodies.size() - 1) { - if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) { - cc.add(new BreakItem(null, currentLoop.id)); - } else { - nextCase = caseBodies.get(i + 1); - } - } else if (!defaultCommands.isEmpty()) { - if (!caseBodies.get(i).leadsTo(localData, this, code, defaultPart, loops)) { - cc.add(new BreakItem(null, currentLoop.id)); - } else { - nextCase = defaultPart; - } - } - } - List stopPart2x = new ArrayList<>(stopPart); - //stopPart2.add(nextCase); - for (GraphPart b : caseBodies) { - if (b != caseBodies.get(i)) { - stopPart2x.add(b); - } - } - if (defaultPart != null) { - stopPart2x.add(defaultPart); - } - if (breakPart != null) { - stopPart2x.add(breakPart); - } - cc.addAll(0, printGraph(localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); - if (cc.size() >= 2) { - if (cc.get(cc.size() - 1) instanceof BreakItem) { - if ((cc.get(cc.size() - 2) instanceof ContinueItem) || (cc.get(cc.size() - 2) instanceof BreakItem)) { - cc.remove(cc.size() - 1); - } - } - } - caseCommands.add(cc); - } - ret = new ArrayList<>(); - ret.addAll(output); - SwitchItem sti = new SwitchItem(null, currentLoop, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping); - ret.add(sti); - currentLoop.phase = 2; - if (next != null) { - if (ti != null) { - ret.add(ti); - } else { - ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); - } - } - } - } - return ret; - } - - @Override - protected int checkIp(int ip) { - int oldIp = ip; - //return in for..in - GraphSourceItem action = code.get(ip); - if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { - if (ip + 3 < code.size()) { - if ((code.get(ip + 1) instanceof ActionEquals) || (code.get(ip + 1) instanceof ActionEquals2)) { - if (code.get(ip + 2) instanceof ActionNot) { - if (code.get(ip + 3) instanceof ActionIf) { - ActionIf aif = (ActionIf) code.get(ip + 3); - if (code.adr2pos(code.pos2adr(ip + 4) + aif.getJumpOffset()) == ip) { - ip += 4; - } - } - } - } - } - } - if (oldIp != ip) { - return checkIp(ip); - } - return ip; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.BaseLocalData; +import com.jpexs.decompiler.flash.FinalProcessLocalData; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem; +import com.jpexs.decompiler.flash.action.model.SetTargetActionItem; +import com.jpexs.decompiler.flash.action.model.SetTypeActionItem; +import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem; +import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem; +import com.jpexs.decompiler.flash.action.model.operations.StrictEqActionItem; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphPart; +import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.Loop; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.BreakItem; +import com.jpexs.decompiler.graph.model.ContinueItem; +import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.SwitchItem; +import com.jpexs.decompiler.graph.model.WhileItem; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class ActionGraph extends Graph { + + public ActionGraph(List code, HashMap registerNames, HashMap variables, HashMap functions, int version) { + super(new ActionGraphSource(code, version, registerNames, variables, functions), new ArrayList()); + //this.version = version; + /*heads = makeGraph(code, new ArrayList()); + for (GraphPart head : heads) { + fixGraph(head); + makeMulti(head, new ArrayList()); + }*/ + } + + public static List translateViaGraph(HashMap registerNames, HashMap variables, HashMap functions, List code, int version, int staticOperation, String path) throws InterruptedException { + + ActionGraph g = new ActionGraph(code, registerNames, variables, functions, version); + ActionLocalData localData = new ActionLocalData(registerNames); + g.init(localData); + return g.translate(localData, staticOperation, path); + } + + @Override + public void finalProcessStack(TranslateStack stack, List output) { + if (stack.size() > 0) { + for (int i = stack.size() - 1; i >= 0; i--) { + //System.err.println(stack.get(i)); + if (stack.get(i) instanceof FunctionActionItem) { + FunctionActionItem f = (FunctionActionItem) stack.remove(i); + if (!output.contains(f)) { + output.add(0, f); + } + } + } + } + } + + @Override + protected void finalProcess(List list, int level, FinalProcessLocalData localData) { + List ret = Action.checkClass(list); + if (ret != list) { + list.clear(); + list.addAll(ret); + } + int targetStart; + int targetEnd; + + boolean again; + do { + again = false; + targetStart = -1; + targetEnd = -1; + GraphTargetItem targetStartItem = null; + GraphTargetItem target = null; + for (int t = 0; t < list.size(); t++) { + GraphTargetItem it = list.get(t); + if (it instanceof SetTargetActionItem) { + SetTargetActionItem st = (SetTargetActionItem) it; + if (st.target.isEmpty()) { + if (targetStart > -1) { + targetEnd = t; + break; + } + } else { + target = new DirectValueActionItem(null, 0, st.target, new ArrayList()); + targetStart = t; + targetStartItem = it; + } + } + if (it instanceof SetTarget2ActionItem) { + SetTarget2ActionItem st = (SetTarget2ActionItem) it; + if ((st.target instanceof DirectValueActionItem) && st.target.getResult().equals("")) { + if (targetStart > -1) { + targetEnd = t; + break; + } + } else { + targetStart = t; + target = st.target; + targetStartItem = it; + } + } + } + if ((targetStart > -1) && (targetEnd > -1)) { + List newlist = new ArrayList<>(); + for (int i = 0; i < targetStart; i++) { + newlist.add(list.get(i)); + } + List tellist = new ArrayList<>(); + for (int i = targetStart + 1; i < targetEnd; i++) { + tellist.add(list.get(i)); + } + newlist.add(new TellTargetActionItem(targetStartItem.src, target, tellist)); + for (int i = targetEnd + 1; i < list.size(); i++) { + newlist.add(list.get(i)); + } + list.clear(); + list.addAll(newlist); + again = true; + } + } while (again); + for (int t = 1/*not first*/; t < list.size(); t++) { + GraphTargetItem it = list.get(t); + if (it instanceof WhileItem) { + WhileItem wi = (WhileItem) it; + if ((!wi.commands.isEmpty()) && (wi.commands.get(0) instanceof SetTypeActionItem)) { + SetTypeActionItem sti = (SetTypeActionItem) wi.commands.get(0); + if (wi.expression.get(wi.expression.size() - 1) instanceof NeqActionItem) { + NeqActionItem ne = (NeqActionItem) wi.expression.get(wi.expression.size() - 1); + if (ne.rightSide instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide; + if (dv.value instanceof Null) { + GraphTargetItem en = list.get(t - 1); + if (en instanceof EnumerateActionItem) { + EnumerateActionItem eti = (EnumerateActionItem) en; + list.remove(t); + wi.commands.remove(0); + list.add(t, new ForInActionItem(null, wi.loop, sti.getObject(), eti.object, wi.commands)); + list.remove(t - 1); + t--; + } + } + + } + } + } + + } + } + //Handle for loops at the end: + super.finalProcess(list, level, localData); + } + + @Override + protected List checkPrecoNextParts(GraphPart part) { + List items = getPartItems(part); + part = makeMultiPart(part); + if (items.size() > 1) { + if (items.get(items.size() - 1) instanceof ActionIf) { + if (items.get(items.size() - 2) instanceof ActionStrictEquals) { + List storeRegisters = new ArrayList<>(); + for (GraphSourceItem s : items) { + if (s instanceof ActionStoreRegister) { + ActionStoreRegister sr = (ActionStoreRegister) s; + storeRegisters.add(sr.registerNumber); + } + } + if (!storeRegisters.isEmpty()) { + List caseBodies = new ArrayList<>(); + boolean proceed = false; + do { + proceed = false; + caseBodies.add(part.nextParts.get(0)); //jump + part = part.nextParts.get(1); //nojump + items = getPartItems(part); + part = makeMultiPart(part); + if (!items.isEmpty()) { + if (items.get(0) instanceof ActionPush) { + ActionPush pu = (ActionPush) items.get(0); + if (!pu.values.isEmpty()) { + if (pu.values.get(0) instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) pu.values.get(0); + if (storeRegisters.contains(rn.number)) { + storeRegisters.clear(); + storeRegisters.add(rn.number); + if (items.get(items.size() - 1) instanceof ActionIf) { + if (items.size() > 1) { + if (items.get(items.size() - 2) instanceof ActionStrictEquals) { + proceed = true; + } + } + } + } + } + } + } + } + } while (proceed); + + if (caseBodies.size() > 1) { + caseBodies.add(part); //TODO: properly detect default clause (?) + return caseBodies; + } + } + } + } + } + return null; + } + + @Override + protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { + if (!output.isEmpty()) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + StoreRegisterActionItem str = (StoreRegisterActionItem) output.get(output.size() - 1); + if (str.value instanceof EnumerateActionItem) { + output.remove(output.size() - 1); + } + } + } + List ret = null; + if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && (stack.peek() instanceof StrictEqActionItem)) { + + GraphTargetItem switchedObject = null; + if (!output.isEmpty()) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + switchedObject = ((StoreRegisterActionItem) output.get(output.size() - 1)).value; + } + } + if (switchedObject == null) { + switchedObject = new DirectValueActionItem(null, -1, new Null(), null); + } + HashMap caseValuesMap = new HashMap<>(); + + int pos = 0; + StrictEqActionItem set = (StrictEqActionItem) stack.pop(); + caseValuesMap.put(pos, set.rightSide); + if (set.leftSide instanceof StoreRegisterActionItem) { + switchedObject = ((StoreRegisterActionItem) set.leftSide).value; + } + //GraphPart switchLoc = part.nextParts.get(1).nextParts.get(0); + List caseBodyParts = new ArrayList<>(); + caseBodyParts.add(part.nextParts.get(0)); + GraphTargetItem top = null; + int cnt = 1; + while (part.nextParts.size() > 1 + && part.nextParts.get(1).getHeight() > 1 + && code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end) instanceof ActionIf + && ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) { + cnt++; + part = part.nextParts.get(1); + pos++; + caseBodyParts.add(part.nextParts.get(0)); + + set = (StrictEqActionItem) top; + caseValuesMap.put(pos, set.rightSide); + } + if (cnt == 1) { + stack.push(set); + } else { + part = part.nextParts.get(1); + + GraphPart defaultPart = part; //21-21 + //caseBodyParts.add(defaultPart); + + List defaultAndLastPart = new ArrayList<>(); + defaultAndLastPart.add(defaultPart); + defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1)); + + GraphPart defaultPart2 = getCommonPart(localData, defaultAndLastPart, loops);//34-37 + + List defaultCommands = new ArrayList<>(); + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(defaultPart2); + defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path); + + List loopContinues = new ArrayList<>(); + for (Loop l : loops) { + if (l.loopContinue != null) { + loopContinues.add(l.loopContinue); + } + } + + List breakParts = new ArrayList<>(); + /*for (int g = 0; g < caseBodyParts.size(); g++) { + if (g < caseBodyParts.size() - 1) { + if (caseBodyParts.get(g).leadsTo(code, caseBodyParts.get(g + 1), loops)) { + continue; + } + } + GraphPart nsp = caseBodyParts.get(g).getNextSuperPartPath(loopContinues); + if (nsp != null) { + breakParts.add(nsp); + } + } + Collections.sort(breakParts, new Comparator() { + @Override + public int compare(GraphPart o1, GraphPart o2) { + return o2.path.length() - o1.path.length(); + } + });*/ + + //GraphPart breakPart = breakParts.isEmpty() ? null : breakParts.get(0); + List mcp = new ArrayList<>(); + mcp.addAll(caseBodyParts); + if (defaultPart2 != null) { + mcp.add(defaultPart2); + } + GraphPart breakPart = getMostCommonPart(localData, mcp, loops); + if ((defaultPart2 != breakPart) && (defaultCommands.isEmpty())) { + defaultPart = defaultPart2; + } + + List caseValues = new ArrayList<>(); + for (int i = 0; i < caseBodyParts.size(); i++) { + if (caseValuesMap.containsKey(i)) { + caseValues.add(caseValuesMap.get(i)); + } else { + continue; + } + } + + List> caseCommands = new ArrayList<>(); + GraphPart next = null; + + next = breakPart; + + GraphTargetItem ti = checkLoop(next, stopPart, loops); + currentLoop = new Loop(loops.size(), null, next); + currentLoop.phase = 1; + loops.add(currentLoop); + //switchLoc.getNextPartPath(new ArrayList()); + List valuesMapping = new ArrayList<>(); + List caseBodies = new ArrayList<>(); + for (int i = 0; i < caseValues.size(); i++) { + GraphPart cur = caseBodyParts.get(i); + if (!caseBodies.contains(cur)) { + caseBodies.add(cur); + } + valuesMapping.add(caseBodies.indexOf(cur)); + } + + if (defaultPart == breakPart) { + defaultPart = null; + } + if ((defaultPart != null) && (defaultCommands.isEmpty())) { + List stopPart2x = new ArrayList<>(stopPart); + stopPart2x.add(next); + defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path); + } + + if (!defaultCommands.isEmpty()) { + if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) { + BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1); + if (bi.loopId == currentLoop.id) { + defaultCommands.remove(defaultCommands.size() - 1); + } + } + } + + List ignored = new ArrayList<>(); + for (Loop l : loops) { + ignored.add(l.loopContinue); + } + + for (int i = 0; i < caseBodies.size(); i++) { + List cc = new ArrayList<>(); + GraphPart nextCase = null; + nextCase = next; + if (next != null) { + if (i < caseBodies.size() - 1) { + if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) { + cc.add(new BreakItem(null, currentLoop.id)); + } else { + nextCase = caseBodies.get(i + 1); + } + } else if (!defaultCommands.isEmpty()) { + if (!caseBodies.get(i).leadsTo(localData, this, code, defaultPart, loops)) { + cc.add(new BreakItem(null, currentLoop.id)); + } else { + nextCase = defaultPart; + } + } + } + List stopPart2x = new ArrayList<>(stopPart); + //stopPart2.add(nextCase); + for (GraphPart b : caseBodies) { + if (b != caseBodies.get(i)) { + stopPart2x.add(b); + } + } + if (defaultPart != null) { + stopPart2x.add(defaultPart); + } + if (breakPart != null) { + stopPart2x.add(breakPart); + } + cc.addAll(0, printGraph(localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); + if (cc.size() >= 2) { + if (cc.get(cc.size() - 1) instanceof BreakItem) { + if ((cc.get(cc.size() - 2) instanceof ContinueItem) || (cc.get(cc.size() - 2) instanceof BreakItem)) { + cc.remove(cc.size() - 1); + } + } + } + caseCommands.add(cc); + } + ret = new ArrayList<>(); + ret.addAll(output); + SwitchItem sti = new SwitchItem(null, currentLoop, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping); + ret.add(sti); + currentLoop.phase = 2; + if (next != null) { + if (ti != null) { + ret.add(ti); + } else { + ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); + } + } + } + } + return ret; + } + + @Override + protected int checkIp(int ip) { + int oldIp = ip; + //return in for..in + GraphSourceItem action = code.get(ip); + if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { + if (ip + 3 < code.size()) { + if ((code.get(ip + 1) instanceof ActionEquals) || (code.get(ip + 1) instanceof ActionEquals2)) { + if (code.get(ip + 2) instanceof ActionNot) { + if (code.get(ip + 3) instanceof ActionIf) { + ActionIf aif = (ActionIf) code.get(ip + 3); + if (code.adr2pos(code.pos2adr(ip + 4) + aif.getJumpOffset()) == ip) { + ip += 4; + } + } + } + } + } + } + if (oldIp != ip) { + return checkIp(ip); + } + return ip; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java index ef574d29f..7f2a6a07a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -1,1011 +1,1011 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action; - -import com.jpexs.decompiler.flash.DisassemblyListener; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; -import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscatorSimple; -import com.jpexs.decompiler.flash.action.model.ConstantPool; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.special.ActionNop; -import com.jpexs.decompiler.flash.action.special.ActionStore; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.NotCompileTimeItem; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Scanner; -import java.util.TreeMap; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Class for reading data from SWF file - * - * @author JPEXS - */ -public class ActionListReader { - - private static final Logger logger = Logger.getLogger(ActionListReader.class.getName()); - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param sis - * @param version - * @param ip - * @param endIp - * @param path - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - * @throws java.util.concurrent.TimeoutException - */ - public static ActionList readActionListTimeout(final List listeners, final SWFInputStream sis, final int version, final int ip, final int endIp, final String path) throws IOException, InterruptedException, TimeoutException { - try { - final int deobfuscationMode = Configuration.autoDeobfuscate.get() ? Configuration.deobfuscationMode.get() : -1; - ActionList actions = CancellableWorker.call(new Callable() { - - @Override - public ActionList call() throws IOException, InterruptedException { - return readActionList(listeners, sis, version, ip, endIp, path, deobfuscationMode); - } - }, Configuration.decompilationTimeoutSingleMethod.get(), TimeUnit.SECONDS); - - return actions; - } catch (ExecutionException ex) { - Throwable cause = ex.getCause(); - if (cause instanceof InterruptedException) { - throw (InterruptedException) cause; - } else if (cause instanceof InterruptedException) { - throw (IOException) cause; - } else { - logger.log(Level.SEVERE, null, ex); - } - } - return new ActionList(); - } - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param sis - * @param version - * @param ip - * @param endIp - * @param path - * @param deobfuscationMode - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - */ - public static ActionList readActionList(List listeners, SWFInputStream sis, int version, int ip, int endIp, String path, int deobfuscationMode) throws IOException, InterruptedException { - // Map of the actions. Use TreeMap to sort the keys in ascending order - // actionMap and nextOffsets should contain exaclty the same keys - Map actionMap = new TreeMap<>(); - Map nextOffsets = new HashMap<>(); - Action entryAction = readActionListAtPos(listeners, null, - sis, actionMap, nextOffsets, - ip, 0, endIp, path, false, new ArrayList()); - - if (actionMap.isEmpty()) { - return new ActionList(); - } - - List addresses = new ArrayList<>(actionMap.keySet()); - - // add end action - Action lastAction = actionMap.get(addresses.get(addresses.size() - 1)); - long endAddress; - if (!(lastAction instanceof ActionEnd)) { - Action aEnd = new ActionEnd(); - aEnd.setAddress(nextOffsets.get(lastAction.getAddress())); - endAddress = aEnd.getAddress(); - actionMap.put(aEnd.getAddress(), aEnd); - nextOffsets.put(endAddress, endAddress + 1); - } - - ActionList actions = fixActionList(new ActionList(actionMap.values()), nextOffsets, version); - - // jump to the entry action when it is diffrent from the first action in the map - if (entryAction != actions.get(0)) { - ActionJump jump = new ActionDeobfuscateJump(0); - actions.addAction(0, jump); - jump.setJumpOffset((int) (entryAction.getAddress() - jump.getTotalActionLength())); - } - - if (SWFDecompilerPlugin.fireActionListParsed(actions, sis.getSwf())) { - actions = fixActionList(actions, null, version); - } - - if (deobfuscationMode == 0) { - try { - actions = deobfuscateActionList(listeners, actions, version, 0, path); - updateActionLengths(actions, version); - } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { - // keep orignal (not deobfuscated) actions - logger.log(Level.SEVERE, null, ex); - } - } else if (deobfuscationMode == 1) { - try { - new ActionDeobfuscatorSimple().actionListParsed(actions, sis.getSwf()); - new ActionDeobfuscator().actionListParsed(actions, sis.getSwf()); - } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { - // keep orignal (not deobfuscated) actions - logger.log(Level.SEVERE, null, ex); - } - } - - return actions; - } - - public static ActionList fixActionList(ActionList actions, Map nextOffsets, int version) { - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - ActionList ret = new ActionList(); - - if (nextOffsets != null) { - int index = 0; - while (index != -1 && index < actions.size()) { - Action action = actions.get(index); - ret.add(action); - index++; - if (index < actions.size()) { - long nextAddress = nextOffsets.get(action.getAddress()); - if (actions.get(index).getAddress() != nextAddress) { - if (!action.isExit() && !(action instanceof ActionJump)) { - ActionJump jump = new ActionDeobfuscateJump(0); - jump.setAddress(action.getAddress()); - int size = jump.getTotalActionLength(); - jump.setJumpOffset((int) (nextAddress - action.getAddress() - size)); - ret.add(jump); - } - } - } - } - } else { - ret.addAll(actions); - } - - // Map for storing the targers of the "jump" actions - // "jump" action can be ActionIf, ActionJump and any ActionStore - Map jumps = new HashMap<>(); - getJumps(ret, jumps); - - updateActionLengths(ret, version); - updateAddresses(ret, 0); - long endAddress = ret.get(ret.size() - 1).getAddress(); - - updateJumps(ret, jumps, containerLastActions, endAddress); - updateActionStores(ret, jumps); - updateContainerSizes(ret, containerLastActions); - - return ret; - } - - public static List getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException { - // Map of the actions. Use TreeMap to sort the keys in ascending order - Map actionMap = new TreeMap<>(); - Map nextOffsets = new HashMap<>(); - readActionListAtPos(new ArrayList(), null, - sis, actionMap, nextOffsets, - startIp, startIp, endIp + 1, "", false, new ArrayList()); - - return new ArrayList<>(actionMap.values()); - } - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param actions - * @param version - * @param ip - * @param path - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - */ - private static ActionList deobfuscateActionList(List listeners, ActionList actions, int version, int ip, String path) throws IOException, InterruptedException { - if (actions.isEmpty()) { - return actions; - } - - Action lastAction = actions.get(actions.size() - 1); - int endIp = (int) lastAction.getAddress(); - - List retMap = new ArrayList<>(endIp); - for (int i = 0; i < endIp; i++) { - retMap.add(null); - } - List actionMap = new ArrayList<>(endIp); - for (int i = 0; i <= endIp; i++) { - actionMap.add(null); - } - for (Action a : actions) { - actionMap.set((int) a.getAddress(), a); - } - - int maxRecursionLevel = 0; - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) { - maxRecursionLevel++; - } - if (a instanceof ActionIf) { - ActionIf aif = (ActionIf) a; - aif.ignoreUsed = false; - aif.jumpUsed = false; - } - } - - deobfustaceActionListAtPosRecursive(listeners, - new ArrayList(), - new HashMap>(), - new ActionLocalData(), - new TranslateStack(), - new ConstantPool(), - actionMap, ip, retMap, ip, endIp, path, - new HashMap(), false, - new HashMap>(), - version, 0, maxRecursionLevel); - - ActionList ret = new ActionList(); - Action last = null; - for (Action a : retMap) { - if (a != last && a != null) { - ret.add(a); - } - last = a; - } - ret.removeNops(); - ActionList reta = new ActionList(); - for (Object o : ret) { - if (o instanceof Action) { - reta.add((Action) o); - } - } - return reta; - } - - private static long getNearAddress(ActionList actions, long address, boolean next) { - int min = 0; - int max = actions.size() - 1; - - while (max >= min) { - int mid = (min + max) / 2; - long midValue = actions.get(mid).getAddress(); - if (midValue == address) { - return address; - } else if (midValue < address) { - min = mid + 1; - } else { - max = mid - 1; - } - } - - return next - ? (min < actions.size() ? actions.get(min).getAddress() : -1) - : (max >= 0 ? actions.get(max).getAddress() : -1); - } - - private static Map actionListToMap(List actions) { - Map map = new HashMap<>(actions.size()); - for (Action a : actions) { - long address = a.getAddress(); - // There are multiple actions in the same address (2nd action is a jump for obfuscated code) - // So this check is required - if (!map.containsKey(address)) { - map.put(a.getAddress(), a); - } - } - return map; - } - - private static void getJumps(List actions, Map jumps) { - Map actionMap = actionListToMap(actions); - for (Action a : actions) { - long target = -1; - if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - target = aIf.getAddress() + a.getTotalActionLength() + aIf.getJumpOffset(); - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - target = aJump.getAddress() + a.getTotalActionLength() + aJump.getJumpOffset(); - } else if (a instanceof ActionStore) { - ActionStore aStore = (ActionStore) a; - int storeSize = aStore.getStoreSize(); - // skip storeSize + 1 actions (+1 is the current action) - Action targetAction = a; - for (int i = 0; i <= storeSize; i++) { - long address = targetAction.getAddress() + targetAction.getTotalActionLength(); - targetAction = actionMap.get(address); - if (targetAction == null) { - break; - } - } - jumps.put(a, targetAction); - } - if (target >= 0) { - Action targetAction = actionMap.get(target); - jumps.put(a, targetAction); - } - } - } - - public static List getContainerLastActions(ActionList actions, Action action) { - GraphSourceItemContainer container = (GraphSourceItemContainer) action; - List sizes = container.getContainerSizes(); - long endAddress = action.getAddress() + container.getHeaderSize(); - List lasts = new ArrayList<>(sizes.size()); - for (long size : sizes) { - endAddress += size; - long lastActionAddress = getNearAddress(actions, endAddress - 1, false); - Action lastAction = null; - if (lastActionAddress != -1) { - lastAction = actions.getByAddress(lastActionAddress); - } - lasts.add(lastAction); - } - return lasts; - } - - private static void getContainerLastActions(ActionList actions, Map> lastActions) { - for (Action a : actions) { - if (a instanceof GraphSourceItemContainer) { - lastActions.put(a, getContainerLastActions(actions, a)); - } - } - } - - private static long updateAddresses(List actions, long address) { - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - a.setAddress(address); - int length = a.getTotalActionLength(); - if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { - // placeholder for jump action - length = new ActionDeobfuscateJump(0).getTotalActionLength(); - } - address += length; - } - return address; - } - - private static void updateActionLengths(List actions, int version) { - for (int i = 0; i < actions.size(); i++) { - actions.get(i).updateLength(version); - } - } - - private static void updateActionStores(List actions, Map jumps) { - Map actionMap = actionListToMap(actions); - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof ActionStore) { - ActionStore aStore = (ActionStore) a; - Action nextActionAfterStore = jumps.get(a); - Action a1 = a; - List store = new ArrayList<>(); - while (true) { - long address = a1.getAddress() + a1.getTotalActionLength(); - a1 = actionMap.get(address); - if (a1 == null || a1 == nextActionAfterStore) { - break; - } - store.add(a1); - } - aStore.setStore(store); - } - } - } - - private static void updateContainerSizes(List actions, Map> containerLastActions) { - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer container = (GraphSourceItemContainer) a; - List lastActions = containerLastActions.get(a); - long startAddress = a.getAddress() + container.getHeaderSize(); - for (int j = 0; j < lastActions.size(); j++) { - Action lastAction = lastActions.get(j); - int length = (int) (lastAction.getAddress() + lastAction.getTotalActionLength() - startAddress); - container.setContainerSize(j, length); - startAddress += length; - } - } - } - } - - private static void replaceJumpTargets(Map jumps, Action oldTarget, Action newTarget) { - for (Action a : jumps.keySet()) { - if (jumps.get(a) == oldTarget) { - jumps.put(a, newTarget); - } - } - } - - private static void replaceContainerLastActions(Map> containerLastActions, Action oldTarget, Action newTarget) { - for (Action a : containerLastActions.keySet()) { - List targets = containerLastActions.get(a); - for (int i = 0; i < targets.size(); i++) { - if (targets.get(i) == oldTarget) { - targets.set(i, newTarget); - } - } - } - } - - private static void updateJumps(List actions, Map jumps, Map> containerLastActions, long endAddress) { - if (actions.isEmpty()) { - return; - } - - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { - ActionJump aJump = new ActionDeobfuscateJump(0); - aJump.setJumpOffset((int) (endAddress - a.getAddress() - aJump.getTotalActionLength())); - aJump.setAddress(a.getAddress()); - replaceJumpTargets(jumps, a, aJump); - replaceContainerLastActions(containerLastActions, a, aJump); - a = aJump; - actions.set(i, a); - } else if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - Action target = jumps.get(a); - long offset; - if (target != null) { - offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); - } else { - offset = endAddress - a.getAddress() - a.getTotalActionLength(); - } - aIf.setJumpOffset((int) offset); - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - Action target = jumps.get(a); - long offset; - if (target != null) { - offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); - } else { - offset = endAddress - a.getAddress() - a.getTotalActionLength(); - } - aJump.setJumpOffset((int) offset); - } - } - } - - /** - * Removes an action from the action list, and updates all references This - * method will keep the inner actions of the container when you remove the - * container - * - * @param actions - * @param index - * @param version - * @param removeWhenLast - * @return - */ - public static boolean removeAction(ActionList actions, int index, int version, boolean removeWhenLast) { - - if (index < 0 || actions.size() <= index) { - return false; - } - - long startIp = actions.get(0).getAddress(); - Action lastAction = actions.get(actions.size() - 1); - long endAddress = lastAction.getAddress() + lastAction.getTotalActionLength(); - - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - Map jumps = new HashMap<>(); - getJumps(actions, jumps); - - Action prevAction = index > 0 ? actions.get(index - 1) : null; - Action nextAction = index + 1 < actions.size() ? actions.get(index + 1) : null; - Action actionToRemove = actions.get(index); - for (Action a : containerLastActions.keySet()) { - List lastActions = containerLastActions.get(a); - for (int i = 0; i < lastActions.size(); i++) { - if (lastActions.get(i) == actionToRemove) { - if (!removeWhenLast) { - return false; - } - lastActions.set(i, prevAction); - } - } - } - for (Action a : jumps.keySet()) { - Action targetAction = jumps.get(a); - if (targetAction == actionToRemove) { - jumps.put(a, nextAction); - } - } - if (containerLastActions.containsKey(actionToRemove)) { - containerLastActions.remove(actionToRemove); - } - if (jumps.containsKey(actionToRemove)) { - jumps.remove(actionToRemove); - } - - actions.remove(index); - - updateActionLengths(actions, version); - updateAddresses(actions, startIp); - updateJumps(actions, jumps, containerLastActions, endAddress); - updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); - - return true; - } - - /** - * Adds an action to the action list to the specified location, and updates - * all references - * - * @param actions - * @param index - * @param action - * @param version - * @param addToContainer - * @param replaceJump - * @return - */ - public static boolean addAction(ActionList actions, int index, Action action, - int version, boolean addToContainer, boolean replaceJump) { - - if (index < 0 || actions.size() < index) { - return false; - } - - long startIp = actions.get(0).getAddress(); - Action lastAction = actions.get(actions.size() - 1); - if (!(lastAction instanceof ActionEnd)) { - Action aEnd = new ActionEnd(); - aEnd.setAddress(lastAction.getAddress() + lastAction.getTotalActionLength()); - actions.add(aEnd); - lastAction = aEnd; - } - - long endAddress = lastAction.getAddress(); - - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - Map jumps = new HashMap<>(); - List tempActions = new ArrayList<>(actions); - tempActions.add(action); - getJumps(tempActions, jumps); - - Action prevAction = actions.get(index); - if (addToContainer) { - for (Action a : containerLastActions.keySet()) { - List lastActions = containerLastActions.get(a); - for (int i = 0; i < lastActions.size(); i++) { - if (lastActions.get(i) == prevAction) { - lastActions.set(i, action); - } - } - } - } - - if (replaceJump) { - for (Action a : jumps.keySet()) { - Action targetAction = jumps.get(a); - if (targetAction == prevAction) { - jumps.put(a, action); - } - } - } - - actions.add(index, action); - - updateActionLengths(actions, version); - updateAddresses(actions, startIp); - updateJumps(actions, jumps, containerLastActions, endAddress); - updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); - - return true; - } - - private static Action readActionListAtPos(List listeners, ConstantPool cpool, - SWFInputStream sis, Map actions, Map nextOffsets, - long ip, long startIp, long endIp, String path, boolean indeterminate, List visitedContainers) throws IOException { - - Action entryAction = null; - - if (visitedContainers.contains(ip)) { - return null; - } - visitedContainers.add(ip); - - Queue jumpQueue = new LinkedList<>(); - jumpQueue.add(ip); - while (!jumpQueue.isEmpty()) { - ip = jumpQueue.remove(); - if (ip < startIp) { - continue; - } - - while (endIp == -1 || endIp > ip) { - sis.seek((int) ip); - - Action a; - if ((a = sis.readAction()) == null) { - break; - } - - int actionLengthWithHeader = a.getTotalActionLength(); - - // unknown action, replace with jump - if (a instanceof ActionNop) { - ActionJump aJump = new ActionDeobfuscateJump(0); - int jumpLength = aJump.getTotalActionLength(); - aJump.setAddress(a.getAddress()); - aJump.setJumpOffset(actionLengthWithHeader - jumpLength); - a = aJump; - actionLengthWithHeader = a.getTotalActionLength(); - } - - if (entryAction == null) { - entryAction = a; - } - - Action existingAction = actions.get(ip); - if (existingAction != null) { - break; - } - - actions.put(ip, a); - nextOffsets.put(ip, ip + actionLengthWithHeader); - - long pos = sis.getPos(); - long length = pos + sis.available(); - for (int i = 0; i < listeners.size(); i++) { - listeners.get(i).progressReading(pos, length); - } - - a.setAddress(ip); - - if (a instanceof ActionPush && cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } else if (a instanceof ActionConstantPool) { - cpool = new ConstantPool(((ActionConstantPool) a).constantPool); - } else if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - long nIp = ip + actionLengthWithHeader + aIf.getJumpOffset(); - if (nIp >= 0) { - jumpQueue.add(nIp); - } - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - long nIp = ip + actionLengthWithHeader + aJump.getJumpOffset(); - if (nIp >= 0) { - jumpQueue.add(nIp); - } - break; - } else if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - String cntName = cnt.getName(); - String newPath = path + (cntName == null ? "" : "/" + cntName); - for (long size : cnt.getContainerSizes()) { - if (size != 0) { - long ip2 = ip + actionLengthWithHeader; - long endIp2 = ip + actionLengthWithHeader + size; - readActionListAtPos(listeners, cpool, - sis, actions, nextOffsets, - ip2, startIp, endIp2, newPath, indeterminate, visitedContainers); - actionLengthWithHeader += size; - } - } - } - - ip += actionLengthWithHeader; - - if (a.isExit()) { - break; - } - } - } - return entryAction; - } - - private static void deobfustaceActionListAtPosRecursive(List listeners, List output, HashMap> containers, ActionLocalData localData, TranslateStack stack, ConstantPool cpool, List actions, int ip, List ret, int startIp, int endip, String path, Map visited, boolean indeterminate, Map> decisionStates, int version, int recursionLevel, int maxRecursionLevel) throws IOException, InterruptedException { - boolean debugMode = false; - boolean decideBranch = false; - - if (recursionLevel > maxRecursionLevel + 1) { - throw new TranslateException("deobfustaceActionListAtPosRecursive max recursion level reached."); - } - - Action a; - Scanner sc = null; - loopip: - while (((endip == -1) || (endip > ip)) && (a = actions.get(ip)) != null) { - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException(); - } - - int actionLen = a.getTotalActionLength(); - if (!visited.containsKey(ip)) { - visited.put(ip, 0); - } - int curVisited = visited.get(ip); - curVisited++; - visited.put(ip, curVisited); - for (int i = 0; i < listeners.size(); i++) { - listeners.get(i).progressDeobfuscating(ip, actions.size()); - } - int info = a.getTotalActionLength(); - - if (a instanceof ActionPush) { - if (cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } - } - - if (debugMode) { - String atos = a.getASMSource(new ActionList(), new HashSet(), ScriptExportMode.PCODE); - if (a instanceof GraphSourceItemContainer) { - atos = a.toString(); - } - System.err.println("readActionListAtPos ip: " + (ip - startIp) + " (0x" + Helper.formatAddress(ip - startIp) + ") " + " action(len " + a.actionLength + "): " + atos + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Helper.stackToString(stack, LocalData.create(cpool)) + " " + Helper.byteArrToString(a.getBytes(version))); - System.err.print("variables: "); - for (Map.Entry v : localData.variables.entrySet()) { - System.err.print("'" + v + "' = " + v.getValue().toString(LocalData.create(cpool)) + ", "); - } - System.err.println(); - String add = ""; - if (a instanceof ActionIf) { - add = " change: " + ((ActionIf) a).getJumpOffset(); - } - if (a instanceof ActionJump) { - add = " change: " + ((ActionJump) a).getJumpOffset(); - } - System.err.println(add); - } - - int newip = -1; - - if (a instanceof ActionConstantPool) { - if (cpool == null) { - cpool = new ConstantPool(); - } - cpool.setNew(((ActionConstantPool) a).constantPool); - } - ActionIf aif = null; - boolean goaif = false; - if (!a.isIgnored()) { - String varname = null; - if (a instanceof StoreTypeAction) { - StoreTypeAction sta = (StoreTypeAction) a; - varname = sta.getVariableName(stack, cpool); - } - - try { - if (a instanceof ActionIf) { - aif = (ActionIf) a; - - GraphTargetItem top = stack.pop(); - int nip = ip + actionLen + aif.getJumpOffset(); - - if (decideBranch) { - System.out.print("newip " + nip + ", "); - System.out.print("Action: jump(j),ignore(i),compute(c)?"); - if (sc == null) { - sc = new Scanner(System.in); - } - String next = sc.next(); - switch (next) { - case "j": - newip = nip; - break; - case "i": - break; - case "c": - goaif = true; - break; - } - } else if (top.isCompileTime() && (!top.hasSideEffect())) { - if (debugMode) { - System.err.print("is compiletime -> "); - } - if (EcmaScript.toBoolean(top.getResult())) { - newip = nip; - aif.jumpUsed = true; - if (debugMode) { - System.err.println("jump"); - } - } else { - aif.ignoreUsed = true; - if (debugMode) { - System.err.println("ignore"); - } - } - } else { - if (debugMode) { - System.err.println("goaif"); - } - goaif = true; - } - } else if (a instanceof ActionJump) { - newip = ip + actionLen + ((ActionJump) a).getJumpOffset(); - } else if (!(a instanceof GraphSourceItemContainer)) { - //return in for..in, TODO:Handle this better way - if (((a instanceof ActionEquals) || (a instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) { - stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); - } - if ((a instanceof ActionStoreRegister) && stack.isEmpty()) { - stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); - } - a.translate(localData, stack, output, Graph.SOP_USE_STATIC/*Graph.SOP_SKIP_STATIC*/, path); - } - } catch (RuntimeException ex) { - logger.log(Level.SEVERE, "Disassembly exception", ex); - break; - } - - HashMap vars = localData.variables; - if (varname != null) { - GraphTargetItem varval = vars.get(varname); - if (varval != null && varval.isCompileTime() && indeterminate) { - vars.put(varname, new NotCompileTimeItem(null, varval)); - } - } - } - for (int i = 0; i < actionLen; i++) { - ret.set(ip + i, a); - } - - if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - if (a instanceof Action) { - long endAddr = a.getAddress() + cnt.getHeaderSize(); - String cntName = cnt.getName(); - List> output2s = new ArrayList<>(); - for (long size : cnt.getContainerSizes()) { - if (size == 0) { - output2s.add(new ArrayList()); - continue; - } - ActionLocalData localData2; - List output2 = new ArrayList<>(); - if ((cnt instanceof ActionDefineFunction) || (cnt instanceof ActionDefineFunction2)) { - localData2 = new ActionLocalData(); - } else { - localData2 = localData; - } - deobfustaceActionListAtPosRecursive(listeners, output2, containers, localData2, new TranslateStack(), cpool, actions, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); - output2s.add(output2); - endAddr += size; - } - cnt.translateContainer(output2s, stack, output, localData.regNames, localData.variables, localData.functions); - ip = (int) endAddr; - continue; - } - } - - if (a instanceof ActionEnd) { - break; - } - if (goaif) { - aif.ignoreUsed = true; - aif.jumpUsed = true; - indeterminate = true; - - HashMap vars = localData.variables; - boolean stateChanged = false; - if (decisionStates.containsKey(ip)) { - HashMap oldstate = decisionStates.get(ip); - if (oldstate.size() != vars.size()) { - stateChanged = true; - } else { - for (String k : vars.keySet()) { - if (!oldstate.containsKey(k)) { - stateChanged = true; - break; - } - if (!vars.get(k).isCompileTime() && oldstate.get(k).isCompileTime()) { - stateChanged = true; - break; - } - } - } - } - HashMap curstate = new HashMap<>(); - curstate.putAll(vars); - decisionStates.put(ip, curstate); - - if ((!stateChanged) && curVisited > 1) { - List branches = new ArrayList<>(); - branches.add(ip + actionLen + aif.getJumpOffset()); - branches.add(ip + actionLen); - for (int br : branches) { - int visc = 0; - if (visited.containsKey(br)) { - visc = visited.get(br); - } - if (visc == 0) {//(localData.regNames), - new HashMap<>(localData.variables), new HashMap<>(localData.functions)); - deobfustaceActionListAtPosRecursive(listeners, output, containers, subLocalData, subStack, cpool, actions, ip + actionLen + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); - } - - if (newip > -1) { - ip = newip; - } else { - ip += info; - } - - if (a.isExit()) { - break; - } - } - for (DisassemblyListener listener : listeners) { - listener.progressDeobfuscating(ip, actions.size()); - } - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscatorSimple; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionNop; +import com.jpexs.decompiler.flash.action.special.ActionStore; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.NotCompileTimeItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Scanner; +import java.util.TreeMap; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Class for reading data from SWF file + * + * @author JPEXS + */ +public class ActionListReader { + + private static final Logger logger = Logger.getLogger(ActionListReader.class.getName()); + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param sis + * @param version + * @param ip + * @param endIp + * @param path + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + * @throws java.util.concurrent.TimeoutException + */ + public static ActionList readActionListTimeout(final List listeners, final SWFInputStream sis, final int version, final int ip, final int endIp, final String path) throws IOException, InterruptedException, TimeoutException { + try { + final int deobfuscationMode = Configuration.autoDeobfuscate.get() ? Configuration.deobfuscationMode.get() : -1; + ActionList actions = CancellableWorker.call(new Callable() { + + @Override + public ActionList call() throws IOException, InterruptedException { + return readActionList(listeners, sis, version, ip, endIp, path, deobfuscationMode); + } + }, Configuration.decompilationTimeoutSingleMethod.get(), TimeUnit.SECONDS); + + return actions; + } catch (ExecutionException ex) { + Throwable cause = ex.getCause(); + if (cause instanceof InterruptedException) { + throw (InterruptedException) cause; + } else if (cause instanceof InterruptedException) { + throw (IOException) cause; + } else { + logger.log(Level.SEVERE, null, ex); + } + } + return new ActionList(); + } + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param sis + * @param version + * @param ip + * @param endIp + * @param path + * @param deobfuscationMode + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + */ + public static ActionList readActionList(List listeners, SWFInputStream sis, int version, int ip, int endIp, String path, int deobfuscationMode) throws IOException, InterruptedException { + // Map of the actions. Use TreeMap to sort the keys in ascending order + // actionMap and nextOffsets should contain exaclty the same keys + Map actionMap = new TreeMap<>(); + Map nextOffsets = new HashMap<>(); + Action entryAction = readActionListAtPos(listeners, null, + sis, actionMap, nextOffsets, + ip, 0, endIp, path, false, new ArrayList()); + + if (actionMap.isEmpty()) { + return new ActionList(); + } + + List addresses = new ArrayList<>(actionMap.keySet()); + + // add end action + Action lastAction = actionMap.get(addresses.get(addresses.size() - 1)); + long endAddress; + if (!(lastAction instanceof ActionEnd)) { + Action aEnd = new ActionEnd(); + aEnd.setAddress(nextOffsets.get(lastAction.getAddress())); + endAddress = aEnd.getAddress(); + actionMap.put(aEnd.getAddress(), aEnd); + nextOffsets.put(endAddress, endAddress + 1); + } + + ActionList actions = fixActionList(new ActionList(actionMap.values()), nextOffsets, version); + + // jump to the entry action when it is diffrent from the first action in the map + if (entryAction != actions.get(0)) { + ActionJump jump = new ActionDeobfuscateJump(0); + actions.addAction(0, jump); + jump.setJumpOffset((int) (entryAction.getAddress() - jump.getTotalActionLength())); + } + + if (SWFDecompilerPlugin.fireActionListParsed(actions, sis.getSwf())) { + actions = fixActionList(actions, null, version); + } + + if (deobfuscationMode == 0) { + try { + actions = deobfuscateActionList(listeners, actions, version, 0, path); + updateActionLengths(actions, version); + } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { + // keep orignal (not deobfuscated) actions + logger.log(Level.SEVERE, null, ex); + } + } else if (deobfuscationMode == 1) { + try { + new ActionDeobfuscatorSimple().actionListParsed(actions, sis.getSwf()); + new ActionDeobfuscator().actionListParsed(actions, sis.getSwf()); + } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { + // keep orignal (not deobfuscated) actions + logger.log(Level.SEVERE, null, ex); + } + } + + return actions; + } + + public static ActionList fixActionList(ActionList actions, Map nextOffsets, int version) { + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + ActionList ret = new ActionList(); + + if (nextOffsets != null) { + int index = 0; + while (index != -1 && index < actions.size()) { + Action action = actions.get(index); + ret.add(action); + index++; + if (index < actions.size()) { + long nextAddress = nextOffsets.get(action.getAddress()); + if (actions.get(index).getAddress() != nextAddress) { + if (!action.isExit() && !(action instanceof ActionJump)) { + ActionJump jump = new ActionDeobfuscateJump(0); + jump.setAddress(action.getAddress()); + int size = jump.getTotalActionLength(); + jump.setJumpOffset((int) (nextAddress - action.getAddress() - size)); + ret.add(jump); + } + } + } + } + } else { + ret.addAll(actions); + } + + // Map for storing the targers of the "jump" actions + // "jump" action can be ActionIf, ActionJump and any ActionStore + Map jumps = new HashMap<>(); + getJumps(ret, jumps); + + updateActionLengths(ret, version); + updateAddresses(ret, 0); + long endAddress = ret.get(ret.size() - 1).getAddress(); + + updateJumps(ret, jumps, containerLastActions, endAddress); + updateActionStores(ret, jumps); + updateContainerSizes(ret, containerLastActions); + + return ret; + } + + public static List getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException { + // Map of the actions. Use TreeMap to sort the keys in ascending order + Map actionMap = new TreeMap<>(); + Map nextOffsets = new HashMap<>(); + readActionListAtPos(new ArrayList(), null, + sis, actionMap, nextOffsets, + startIp, startIp, endIp + 1, "", false, new ArrayList()); + + return new ArrayList<>(actionMap.values()); + } + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param actions + * @param version + * @param ip + * @param path + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + */ + private static ActionList deobfuscateActionList(List listeners, ActionList actions, int version, int ip, String path) throws IOException, InterruptedException { + if (actions.isEmpty()) { + return actions; + } + + Action lastAction = actions.get(actions.size() - 1); + int endIp = (int) lastAction.getAddress(); + + List retMap = new ArrayList<>(endIp); + for (int i = 0; i < endIp; i++) { + retMap.add(null); + } + List actionMap = new ArrayList<>(endIp); + for (int i = 0; i <= endIp; i++) { + actionMap.add(null); + } + for (Action a : actions) { + actionMap.set((int) a.getAddress(), a); + } + + int maxRecursionLevel = 0; + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) { + maxRecursionLevel++; + } + if (a instanceof ActionIf) { + ActionIf aif = (ActionIf) a; + aif.ignoreUsed = false; + aif.jumpUsed = false; + } + } + + deobfustaceActionListAtPosRecursive(listeners, + new ArrayList(), + new HashMap>(), + new ActionLocalData(), + new TranslateStack(path), + new ConstantPool(), + actionMap, ip, retMap, ip, endIp, path, + new HashMap(), false, + new HashMap>(), + version, 0, maxRecursionLevel); + + ActionList ret = new ActionList(); + Action last = null; + for (Action a : retMap) { + if (a != last && a != null) { + ret.add(a); + } + last = a; + } + ret.removeNops(); + ActionList reta = new ActionList(); + for (Object o : ret) { + if (o instanceof Action) { + reta.add((Action) o); + } + } + return reta; + } + + private static long getNearAddress(ActionList actions, long address, boolean next) { + int min = 0; + int max = actions.size() - 1; + + while (max >= min) { + int mid = (min + max) / 2; + long midValue = actions.get(mid).getAddress(); + if (midValue == address) { + return address; + } else if (midValue < address) { + min = mid + 1; + } else { + max = mid - 1; + } + } + + return next + ? (min < actions.size() ? actions.get(min).getAddress() : -1) + : (max >= 0 ? actions.get(max).getAddress() : -1); + } + + private static Map actionListToMap(List actions) { + Map map = new HashMap<>(actions.size()); + for (Action a : actions) { + long address = a.getAddress(); + // There are multiple actions in the same address (2nd action is a jump for obfuscated code) + // So this check is required + if (!map.containsKey(address)) { + map.put(a.getAddress(), a); + } + } + return map; + } + + private static void getJumps(List actions, Map jumps) { + Map actionMap = actionListToMap(actions); + for (Action a : actions) { + long target = -1; + if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + target = aIf.getAddress() + a.getTotalActionLength() + aIf.getJumpOffset(); + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + target = aJump.getAddress() + a.getTotalActionLength() + aJump.getJumpOffset(); + } else if (a instanceof ActionStore) { + ActionStore aStore = (ActionStore) a; + int storeSize = aStore.getStoreSize(); + // skip storeSize + 1 actions (+1 is the current action) + Action targetAction = a; + for (int i = 0; i <= storeSize; i++) { + long address = targetAction.getAddress() + targetAction.getTotalActionLength(); + targetAction = actionMap.get(address); + if (targetAction == null) { + break; + } + } + jumps.put(a, targetAction); + } + if (target >= 0) { + Action targetAction = actionMap.get(target); + jumps.put(a, targetAction); + } + } + } + + public static List getContainerLastActions(ActionList actions, Action action) { + GraphSourceItemContainer container = (GraphSourceItemContainer) action; + List sizes = container.getContainerSizes(); + long endAddress = action.getAddress() + container.getHeaderSize(); + List lasts = new ArrayList<>(sizes.size()); + for (long size : sizes) { + endAddress += size; + long lastActionAddress = getNearAddress(actions, endAddress - 1, false); + Action lastAction = null; + if (lastActionAddress != -1) { + lastAction = actions.getByAddress(lastActionAddress); + } + lasts.add(lastAction); + } + return lasts; + } + + private static void getContainerLastActions(ActionList actions, Map> lastActions) { + for (Action a : actions) { + if (a instanceof GraphSourceItemContainer) { + lastActions.put(a, getContainerLastActions(actions, a)); + } + } + } + + private static long updateAddresses(List actions, long address) { + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + a.setAddress(address); + int length = a.getTotalActionLength(); + if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { + // placeholder for jump action + length = new ActionDeobfuscateJump(0).getTotalActionLength(); + } + address += length; + } + return address; + } + + private static void updateActionLengths(List actions, int version) { + for (int i = 0; i < actions.size(); i++) { + actions.get(i).updateLength(version); + } + } + + private static void updateActionStores(List actions, Map jumps) { + Map actionMap = actionListToMap(actions); + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof ActionStore) { + ActionStore aStore = (ActionStore) a; + Action nextActionAfterStore = jumps.get(a); + Action a1 = a; + List store = new ArrayList<>(); + while (true) { + long address = a1.getAddress() + a1.getTotalActionLength(); + a1 = actionMap.get(address); + if (a1 == null || a1 == nextActionAfterStore) { + break; + } + store.add(a1); + } + aStore.setStore(store); + } + } + } + + private static void updateContainerSizes(List actions, Map> containerLastActions) { + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer container = (GraphSourceItemContainer) a; + List lastActions = containerLastActions.get(a); + long startAddress = a.getAddress() + container.getHeaderSize(); + for (int j = 0; j < lastActions.size(); j++) { + Action lastAction = lastActions.get(j); + int length = (int) (lastAction.getAddress() + lastAction.getTotalActionLength() - startAddress); + container.setContainerSize(j, length); + startAddress += length; + } + } + } + } + + private static void replaceJumpTargets(Map jumps, Action oldTarget, Action newTarget) { + for (Action a : jumps.keySet()) { + if (jumps.get(a) == oldTarget) { + jumps.put(a, newTarget); + } + } + } + + private static void replaceContainerLastActions(Map> containerLastActions, Action oldTarget, Action newTarget) { + for (Action a : containerLastActions.keySet()) { + List targets = containerLastActions.get(a); + for (int i = 0; i < targets.size(); i++) { + if (targets.get(i) == oldTarget) { + targets.set(i, newTarget); + } + } + } + } + + private static void updateJumps(List actions, Map jumps, Map> containerLastActions, long endAddress) { + if (actions.isEmpty()) { + return; + } + + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { + ActionJump aJump = new ActionDeobfuscateJump(0); + aJump.setJumpOffset((int) (endAddress - a.getAddress() - aJump.getTotalActionLength())); + aJump.setAddress(a.getAddress()); + replaceJumpTargets(jumps, a, aJump); + replaceContainerLastActions(containerLastActions, a, aJump); + a = aJump; + actions.set(i, a); + } else if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + Action target = jumps.get(a); + long offset; + if (target != null) { + offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); + } else { + offset = endAddress - a.getAddress() - a.getTotalActionLength(); + } + aIf.setJumpOffset((int) offset); + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + Action target = jumps.get(a); + long offset; + if (target != null) { + offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); + } else { + offset = endAddress - a.getAddress() - a.getTotalActionLength(); + } + aJump.setJumpOffset((int) offset); + } + } + } + + /** + * Removes an action from the action list, and updates all references This + * method will keep the inner actions of the container when you remove the + * container + * + * @param actions + * @param index + * @param version + * @param removeWhenLast + * @return + */ + public static boolean removeAction(ActionList actions, int index, int version, boolean removeWhenLast) { + + if (index < 0 || actions.size() <= index) { + return false; + } + + long startIp = actions.get(0).getAddress(); + Action lastAction = actions.get(actions.size() - 1); + long endAddress = lastAction.getAddress() + lastAction.getTotalActionLength(); + + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + Map jumps = new HashMap<>(); + getJumps(actions, jumps); + + Action prevAction = index > 0 ? actions.get(index - 1) : null; + Action nextAction = index + 1 < actions.size() ? actions.get(index + 1) : null; + Action actionToRemove = actions.get(index); + for (Action a : containerLastActions.keySet()) { + List lastActions = containerLastActions.get(a); + for (int i = 0; i < lastActions.size(); i++) { + if (lastActions.get(i) == actionToRemove) { + if (!removeWhenLast) { + return false; + } + lastActions.set(i, prevAction); + } + } + } + for (Action a : jumps.keySet()) { + Action targetAction = jumps.get(a); + if (targetAction == actionToRemove) { + jumps.put(a, nextAction); + } + } + if (containerLastActions.containsKey(actionToRemove)) { + containerLastActions.remove(actionToRemove); + } + if (jumps.containsKey(actionToRemove)) { + jumps.remove(actionToRemove); + } + + actions.remove(index); + + updateActionLengths(actions, version); + updateAddresses(actions, startIp); + updateJumps(actions, jumps, containerLastActions, endAddress); + updateActionStores(actions, jumps); + updateContainerSizes(actions, containerLastActions); + + return true; + } + + /** + * Adds an action to the action list to the specified location, and updates + * all references + * + * @param actions + * @param index + * @param action + * @param version + * @param addToContainer + * @param replaceJump + * @return + */ + public static boolean addAction(ActionList actions, int index, Action action, + int version, boolean addToContainer, boolean replaceJump) { + + if (index < 0 || actions.size() < index) { + return false; + } + + long startIp = actions.get(0).getAddress(); + Action lastAction = actions.get(actions.size() - 1); + if (!(lastAction instanceof ActionEnd)) { + Action aEnd = new ActionEnd(); + aEnd.setAddress(lastAction.getAddress() + lastAction.getTotalActionLength()); + actions.add(aEnd); + lastAction = aEnd; + } + + long endAddress = lastAction.getAddress(); + + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + Map jumps = new HashMap<>(); + List tempActions = new ArrayList<>(actions); + tempActions.add(action); + getJumps(tempActions, jumps); + + Action prevAction = actions.get(index); + if (addToContainer) { + for (Action a : containerLastActions.keySet()) { + List lastActions = containerLastActions.get(a); + for (int i = 0; i < lastActions.size(); i++) { + if (lastActions.get(i) == prevAction) { + lastActions.set(i, action); + } + } + } + } + + if (replaceJump) { + for (Action a : jumps.keySet()) { + Action targetAction = jumps.get(a); + if (targetAction == prevAction) { + jumps.put(a, action); + } + } + } + + actions.add(index, action); + + updateActionLengths(actions, version); + updateAddresses(actions, startIp); + updateJumps(actions, jumps, containerLastActions, endAddress); + updateActionStores(actions, jumps); + updateContainerSizes(actions, containerLastActions); + + return true; + } + + private static Action readActionListAtPos(List listeners, ConstantPool cpool, + SWFInputStream sis, Map actions, Map nextOffsets, + long ip, long startIp, long endIp, String path, boolean indeterminate, List visitedContainers) throws IOException { + + Action entryAction = null; + + if (visitedContainers.contains(ip)) { + return null; + } + visitedContainers.add(ip); + + Queue jumpQueue = new LinkedList<>(); + jumpQueue.add(ip); + while (!jumpQueue.isEmpty()) { + ip = jumpQueue.remove(); + if (ip < startIp) { + continue; + } + + while (endIp == -1 || endIp > ip) { + sis.seek((int) ip); + + Action a; + if ((a = sis.readAction()) == null) { + break; + } + + int actionLengthWithHeader = a.getTotalActionLength(); + + // unknown action, replace with jump + if (a instanceof ActionNop) { + ActionJump aJump = new ActionDeobfuscateJump(0); + int jumpLength = aJump.getTotalActionLength(); + aJump.setAddress(a.getAddress()); + aJump.setJumpOffset(actionLengthWithHeader - jumpLength); + a = aJump; + actionLengthWithHeader = a.getTotalActionLength(); + } + + if (entryAction == null) { + entryAction = a; + } + + Action existingAction = actions.get(ip); + if (existingAction != null) { + break; + } + + actions.put(ip, a); + nextOffsets.put(ip, ip + actionLengthWithHeader); + + long pos = sis.getPos(); + long length = pos + sis.available(); + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).progressReading(pos, length); + } + + a.setAddress(ip); + + if (a instanceof ActionPush && cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } else if (a instanceof ActionConstantPool) { + cpool = new ConstantPool(((ActionConstantPool) a).constantPool); + } else if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + long nIp = ip + actionLengthWithHeader + aIf.getJumpOffset(); + if (nIp >= 0) { + jumpQueue.add(nIp); + } + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + long nIp = ip + actionLengthWithHeader + aJump.getJumpOffset(); + if (nIp >= 0) { + jumpQueue.add(nIp); + } + break; + } else if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + String cntName = cnt.getName(); + String newPath = path + (cntName == null ? "" : "/" + cntName); + for (long size : cnt.getContainerSizes()) { + if (size != 0) { + long ip2 = ip + actionLengthWithHeader; + long endIp2 = ip + actionLengthWithHeader + size; + readActionListAtPos(listeners, cpool, + sis, actions, nextOffsets, + ip2, startIp, endIp2, newPath, indeterminate, visitedContainers); + actionLengthWithHeader += size; + } + } + } + + ip += actionLengthWithHeader; + + if (a.isExit()) { + break; + } + } + } + return entryAction; + } + + private static void deobfustaceActionListAtPosRecursive(List listeners, List output, HashMap> containers, ActionLocalData localData, TranslateStack stack, ConstantPool cpool, List actions, int ip, List ret, int startIp, int endip, String path, Map visited, boolean indeterminate, Map> decisionStates, int version, int recursionLevel, int maxRecursionLevel) throws IOException, InterruptedException { + boolean debugMode = false; + boolean decideBranch = false; + + if (recursionLevel > maxRecursionLevel + 1) { + throw new TranslateException("deobfustaceActionListAtPosRecursive max recursion level reached."); + } + + Action a; + Scanner sc = null; + loopip: + while (((endip == -1) || (endip > ip)) && (a = actions.get(ip)) != null) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + + int actionLen = a.getTotalActionLength(); + if (!visited.containsKey(ip)) { + visited.put(ip, 0); + } + int curVisited = visited.get(ip); + curVisited++; + visited.put(ip, curVisited); + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).progressDeobfuscating(ip, actions.size()); + } + int info = a.getTotalActionLength(); + + if (a instanceof ActionPush) { + if (cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } + } + + if (debugMode) { + String atos = a.getASMSource(new ActionList(), new HashSet(), ScriptExportMode.PCODE); + if (a instanceof GraphSourceItemContainer) { + atos = a.toString(); + } + System.err.println("readActionListAtPos ip: " + (ip - startIp) + " (0x" + Helper.formatAddress(ip - startIp) + ") " + " action(len " + a.actionLength + "): " + atos + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Helper.stackToString(stack, LocalData.create(cpool)) + " " + Helper.byteArrToString(a.getBytes(version))); + System.err.print("variables: "); + for (Map.Entry v : localData.variables.entrySet()) { + System.err.print("'" + v + "' = " + v.getValue().toString(LocalData.create(cpool)) + ", "); + } + System.err.println(); + String add = ""; + if (a instanceof ActionIf) { + add = " change: " + ((ActionIf) a).getJumpOffset(); + } + if (a instanceof ActionJump) { + add = " change: " + ((ActionJump) a).getJumpOffset(); + } + System.err.println(add); + } + + int newip = -1; + + if (a instanceof ActionConstantPool) { + if (cpool == null) { + cpool = new ConstantPool(); + } + cpool.setNew(((ActionConstantPool) a).constantPool); + } + ActionIf aif = null; + boolean goaif = false; + if (!a.isIgnored()) { + String varname = null; + if (a instanceof StoreTypeAction) { + StoreTypeAction sta = (StoreTypeAction) a; + varname = sta.getVariableName(stack, cpool); + } + + try { + if (a instanceof ActionIf) { + aif = (ActionIf) a; + + GraphTargetItem top = stack.pop(); + int nip = ip + actionLen + aif.getJumpOffset(); + + if (decideBranch) { + System.out.print("newip " + nip + ", "); + System.out.print("Action: jump(j),ignore(i),compute(c)?"); + if (sc == null) { + sc = new Scanner(System.in); + } + String next = sc.next(); + switch (next) { + case "j": + newip = nip; + break; + case "i": + break; + case "c": + goaif = true; + break; + } + } else if (top.isCompileTime() && (!top.hasSideEffect())) { + if (debugMode) { + System.err.print("is compiletime -> "); + } + if (EcmaScript.toBoolean(top.getResult())) { + newip = nip; + aif.jumpUsed = true; + if (debugMode) { + System.err.println("jump"); + } + } else { + aif.ignoreUsed = true; + if (debugMode) { + System.err.println("ignore"); + } + } + } else { + if (debugMode) { + System.err.println("goaif"); + } + goaif = true; + } + } else if (a instanceof ActionJump) { + newip = ip + actionLen + ((ActionJump) a).getJumpOffset(); + } else if (!(a instanceof GraphSourceItemContainer)) { + //return in for..in, TODO:Handle this better way + if (((a instanceof ActionEquals) || (a instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) { + stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); + } + if ((a instanceof ActionStoreRegister) && stack.isEmpty()) { + stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); + } + a.translate(localData, stack, output, Graph.SOP_USE_STATIC/*Graph.SOP_SKIP_STATIC*/, path); + } + } catch (RuntimeException ex) { + logger.log(Level.SEVERE, "Disassembly exception", ex); + break; + } + + HashMap vars = localData.variables; + if (varname != null) { + GraphTargetItem varval = vars.get(varname); + if (varval != null && varval.isCompileTime() && indeterminate) { + vars.put(varname, new NotCompileTimeItem(null, varval)); + } + } + } + for (int i = 0; i < actionLen; i++) { + ret.set(ip + i, a); + } + + if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + if (a instanceof Action) { + long endAddr = a.getAddress() + cnt.getHeaderSize(); + String cntName = cnt.getName(); + List> output2s = new ArrayList<>(); + for (long size : cnt.getContainerSizes()) { + if (size == 0) { + output2s.add(new ArrayList()); + continue; + } + ActionLocalData localData2; + List output2 = new ArrayList<>(); + if ((cnt instanceof ActionDefineFunction) || (cnt instanceof ActionDefineFunction2)) { + localData2 = new ActionLocalData(); + } else { + localData2 = localData; + } + deobfustaceActionListAtPosRecursive(listeners, output2, containers, localData2, new TranslateStack(path), cpool, actions, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); + output2s.add(output2); + endAddr += size; + } + cnt.translateContainer(output2s, stack, output, localData.regNames, localData.variables, localData.functions); + ip = (int) endAddr; + continue; + } + } + + if (a instanceof ActionEnd) { + break; + } + if (goaif) { + aif.ignoreUsed = true; + aif.jumpUsed = true; + indeterminate = true; + + HashMap vars = localData.variables; + boolean stateChanged = false; + if (decisionStates.containsKey(ip)) { + HashMap oldstate = decisionStates.get(ip); + if (oldstate.size() != vars.size()) { + stateChanged = true; + } else { + for (String k : vars.keySet()) { + if (!oldstate.containsKey(k)) { + stateChanged = true; + break; + } + if (!vars.get(k).isCompileTime() && oldstate.get(k).isCompileTime()) { + stateChanged = true; + break; + } + } + } + } + HashMap curstate = new HashMap<>(); + curstate.putAll(vars); + decisionStates.put(ip, curstate); + + if ((!stateChanged) && curVisited > 1) { + List branches = new ArrayList<>(); + branches.add(ip + actionLen + aif.getJumpOffset()); + branches.add(ip + actionLen); + for (int br : branches) { + int visc = 0; + if (visited.containsKey(br)) { + visc = visited.get(br); + } + if (visc == 0) {//(localData.regNames), + new HashMap<>(localData.variables), new HashMap<>(localData.functions)); + deobfustaceActionListAtPosRecursive(listeners, output, containers, subLocalData, subStack, cpool, actions, ip + actionLen + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); + } + + if (newip > -1) { + ip = newip; + } else { + ip += info; + } + + if (a.isExit()) { + break; + } + } + for (DisassemblyListener listener : listeners) { + listener.progressDeobfuscating(ip, actions.size()); + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java index 802b3342c..b51764d96 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java @@ -223,7 +223,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple { private void executeActions(ActionList actions, int idx, int endIdx, ActionConstantPool constantPool, ExecutionResult result, Map fakeFunctions) { List output = new ArrayList<>(); ActionLocalData localData = new ActionLocalData(); - FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(); + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); int instructionsProcessed = 0; ActionConstantPool lastConstantPool = null; @@ -442,7 +442,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple { public Set defines = new HashSet<>(); - public TranslateStack stack = new TranslateStack(); + public TranslateStack stack = new TranslateStack("?"); public Object resultValue; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java index 2bea33d89..6b90466f7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java @@ -273,7 +273,7 @@ public class ActionDeobfuscatorSimple implements SWFDecompilerListener { private void executeActions(ActionList actions, int idx, int endIdx, ExecutionResult result) { List output = new ArrayList<>(); ActionLocalData localData = new ActionLocalData(); - FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(); + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); int instructionsProcessed = 0; try { @@ -388,7 +388,7 @@ public class ActionDeobfuscatorSimple implements SWFDecompilerListener { public int instructionsProcessed = -1; - public TranslateStack stack = new TranslateStack(); + public TranslateStack stack = new TranslateStack("?"); public Object resultValue; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java index 133476812..677710042 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.deobfuscation; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -26,6 +27,10 @@ public class FixItemCounterTranslateStack extends TranslateStack { private int fixItemCount = Integer.MAX_VALUE; + public FixItemCounterTranslateStack(String path) { + super(null); //null path => do not add PushItems + } + @Override public GraphTargetItem pop() { GraphTargetItem result = super.pop(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java index 90db8cbd4..df202ca02 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.Helper; @@ -34,7 +35,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; -public class DirectValueActionItem extends ActionItem { +public class DirectValueActionItem extends ActionItem implements SimpleValue { public Object value; @@ -91,6 +92,11 @@ public class DirectValueActionItem extends ActionItem { return value; } + @Override + public boolean isSimpleValue() { + return !(value instanceof RegisterNumber); + } + @Override public String toStringNoQuotes(LocalData localData) { if (value instanceof Double) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/EnumerateActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/EnumerateActionItem.java index 99809b9aa..e286e5053 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/EnumerateActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/EnumerateActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; @@ -41,8 +42,9 @@ public class EnumerateActionItem extends ActionItem { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("enumerate "); - return object.toString(writer, localData); + writer.append("§§enumerate("); + object.toString(writer, localData); + return writer.append(")"); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/EqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/EqActionItem.java index 1508f005f..4408950b3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/EqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/EqActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class EqActionItem extends BinaryOpItem implements LogicalOpItem { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new NeqActionItem(src, leftSide, rightSide, version2); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GeActionItem.java index 30bb365a3..c33f6375f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GeActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -58,7 +59,7 @@ public class GeActionItem extends BinaryOpItem implements LogicalOpItem, Inverte } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new LtActionItem(src, leftSide, rightSide, version2); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GtActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GtActionItem.java index 7cb210db6..29b3a6528 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GtActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GtActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -42,7 +43,7 @@ public class GtActionItem extends BinaryOpItem implements LogicalOpItem { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new LeActionItem(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/Inverted.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/Inverted.java index 834c918ec..df7e5ac6e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/Inverted.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/Inverted.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; +import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; /** @@ -23,5 +25,5 @@ import com.jpexs.decompiler.graph.GraphTargetItem; */ public interface Inverted { - public GraphTargetItem invert(); + public GraphTargetItem invert(GraphSourceItem src); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LeActionItem.java index 9cbeb028a..76ef25950 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LeActionItem.java @@ -50,7 +50,7 @@ public class LeActionItem extends BinaryOpItem implements LogicalOpItem, Inverte } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new GtActionItem(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LtActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LtActionItem.java index 87f51504d..9d4b8c702 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LtActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LtActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -50,7 +51,7 @@ public class LtActionItem extends BinaryOpItem implements LogicalOpItem { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new GeActionItem(src, leftSide, rightSide, version2); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/NeqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/NeqActionItem.java index 463efa58a..2b2a31bfd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/NeqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/NeqActionItem.java @@ -49,7 +49,7 @@ public class NeqActionItem extends BinaryOpItem implements LogicalOpItem, Invert } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new EqActionItem(src, leftSide, rightSide, version2); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictEqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictEqActionItem.java index 91ab8b2cc..c25133620 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictEqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictEqActionItem.java @@ -42,7 +42,7 @@ public class StrictEqActionItem extends BinaryOpItem implements LogicalOpItem, I } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StrictNeqActionItem(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictNeqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictNeqActionItem.java index f7331a689..47f6986da 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictNeqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictNeqActionItem.java @@ -43,7 +43,7 @@ public class StrictNeqActionItem extends BinaryOpItem implements LogicalOpItem, } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StrictEqActionItem(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringEqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringEqActionItem.java index 0b0d9a432..f122b47de 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringEqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringEqActionItem.java @@ -48,7 +48,7 @@ public class StringEqActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringNeActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGeActionItem.java index 84c262ffd..dabc07d66 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGeActionItem.java @@ -49,7 +49,7 @@ public class StringGeActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringLtActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGtActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGtActionItem.java index 941d8d00e..1df7f826a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGtActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGtActionItem.java @@ -54,7 +54,7 @@ public class StringGtActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringLeActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLeActionItem.java index 4815f27cd..4f42a55b2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLeActionItem.java @@ -57,7 +57,7 @@ public class StringLeActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringGtActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLtActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLtActionItem.java index f90ac8046..c85bfa334 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLtActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLtActionItem.java @@ -48,7 +48,7 @@ public class StringLtActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringGeActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringNeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringNeActionItem.java index f24f2d5da..9027886d3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringNeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringNeActionItem.java @@ -49,7 +49,7 @@ public class StringNeActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringEqActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java index 04477c044..12a1d8506 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java @@ -17,1253 +17,1207 @@ * License along with this library. */ package com.jpexs.decompiler.flash.action.parser.script; - import com.jpexs.decompiler.flash.action.parser.ActionParseException; import java.util.ArrayList; import java.util.List; import java.util.Stack; + /** - * This class is a scanner generated by - * JFlex 1.6.0 from the specification file - * D:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript_script.flex + * This class is a scanner generated by + * JFlex 1.6.0 + * from the specification file C:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript_script.flex */ public final class ActionScriptLexer { - /** - * This character denotes the end of file - */ - public static final int YYEOF = -1; + /** This character denotes the end of file */ + public static final int YYEOF = -1; - /** - * initial size of the lookahead buffer - */ - private static final int ZZ_BUFFERSIZE = 16384; + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; - /** - * lexical states - */ - public static final int YYINITIAL = 0; + /** lexical states */ + public static final int YYINITIAL = 0; + public static final int STRING = 2; + public static final int CHARLITERAL = 4; + public static final int XMLSTARTTAG = 6; + public static final int XML = 8; + public static final int OIDENTIFIER = 10; - public static final int STRING = 2; + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 + }; - public static final int CHARLITERAL = 4; + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\7\1\3\1\2\1\121\1\122\1\1\16\7\4\0\1\14\1\110"+ + "\1\16\1\0\1\6\1\117\1\113\1\30\1\100\1\101\1\5\1\115"+ + "\1\107\1\26\1\11\1\4\1\17\3\23\4\24\2\20\1\10\1\106"+ + "\1\12\1\15\1\13\1\112\1\120\1\62\1\22\1\72\1\73\1\25"+ + "\1\64\1\6\1\66\1\77\2\6\1\70\1\71\1\76\1\6\1\75"+ + "\1\67\1\6\1\63\1\65\1\61\1\74\1\6\1\21\2\6\1\104"+ + "\1\27\1\105\1\116\1\6\1\0\1\35\1\32\1\37\1\46\1\34"+ + "\1\47\1\60\1\52\1\44\1\6\1\36\1\50\1\55\1\42\1\41"+ + "\1\53\1\6\1\33\1\40\1\43\1\45\1\56\1\51\1\57\1\54"+ + "\1\6\1\102\1\114\1\103\1\111\6\7\1\123\32\7\2\0\4\6"+ + "\1\0\1\31\2\0\1\6\2\0\1\7\7\0\1\6\4\0\1\6"+ + "\5\0\27\6\1\0\37\6\1\0\u01ca\6\4\0\14\6\16\0\5\6"+ + "\7\0\1\6\1\0\1\6\21\0\160\7\5\6\1\0\2\6\2\0"+ + "\4\6\10\0\1\6\1\0\3\6\1\0\1\6\1\0\24\6\1\0"+ + "\123\6\1\0\213\6\1\0\5\7\2\0\236\6\11\0\46\6\2\0"+ + "\1\6\7\0\47\6\7\0\1\6\1\0\55\7\1\0\1\7\1\0"+ + "\2\7\1\0\2\7\1\0\1\7\10\0\33\6\5\0\3\6\15\0"+ + "\5\7\6\0\1\6\4\0\13\7\5\0\53\6\37\7\4\0\2\6"+ + "\1\7\143\6\1\0\1\6\10\7\1\0\6\7\2\6\2\7\1\0"+ + "\4\7\2\6\12\7\3\6\2\0\1\6\17\0\1\7\1\6\1\7"+ + "\36\6\33\7\2\0\131\6\13\7\1\6\16\0\12\7\41\6\11\7"+ + "\2\6\4\0\1\6\5\0\26\6\4\7\1\6\11\7\1\6\3\7"+ + "\1\6\5\7\22\0\31\6\3\7\104\0\1\6\1\0\13\6\67\0"+ + "\33\7\1\0\4\7\66\6\3\7\1\6\22\7\1\6\7\7\12\6"+ + "\2\7\2\0\12\7\1\0\7\6\1\0\7\6\1\0\3\7\1\0"+ + "\10\6\2\0\2\6\2\0\26\6\1\0\7\6\1\0\1\6\3\0"+ + "\4\6\2\0\1\7\1\6\7\7\2\0\2\7\2\0\3\7\1\6"+ + "\10\0\1\7\4\0\2\6\1\0\3\6\2\7\2\0\12\7\4\6"+ + "\7\0\1\6\5\0\3\7\1\0\6\6\4\0\2\6\2\0\26\6"+ + "\1\0\7\6\1\0\2\6\1\0\2\6\1\0\2\6\2\0\1\7"+ + "\1\0\5\7\4\0\2\7\2\0\3\7\3\0\1\7\7\0\4\6"+ + "\1\0\1\6\7\0\14\7\3\6\1\7\13\0\3\7\1\0\11\6"+ + "\1\0\3\6\1\0\26\6\1\0\7\6\1\0\2\6\1\0\5\6"+ + "\2\0\1\7\1\6\10\7\1\0\3\7\1\0\3\7\2\0\1\6"+ + "\17\0\2\6\2\7\2\0\12\7\1\0\1\6\17\0\3\7\1\0"+ + "\10\6\2\0\2\6\2\0\26\6\1\0\7\6\1\0\2\6\1\0"+ + "\5\6\2\0\1\7\1\6\7\7\2\0\2\7\2\0\3\7\10\0"+ + "\2\7\4\0\2\6\1\0\3\6\2\7\2\0\12\7\1\0\1\6"+ + "\20\0\1\7\1\6\1\0\6\6\3\0\3\6\1\0\4\6\3\0"+ + "\2\6\1\0\1\6\1\0\2\6\3\0\2\6\3\0\3\6\3\0"+ + "\14\6\4\0\5\7\3\0\3\7\1\0\4\7\2\0\1\6\6\0"+ + "\1\7\16\0\12\7\11\0\1\6\7\0\3\7\1\0\10\6\1\0"+ + "\3\6\1\0\27\6\1\0\12\6\1\0\5\6\3\0\1\6\7\7"+ + "\1\0\3\7\1\0\4\7\7\0\2\7\1\0\2\6\6\0\2\6"+ + "\2\7\2\0\12\7\22\0\2\7\1\0\10\6\1\0\3\6\1\0"+ + "\27\6\1\0\12\6\1\0\5\6\2\0\1\7\1\6\7\7\1\0"+ + "\3\7\1\0\4\7\7\0\2\7\7\0\1\6\1\0\2\6\2\7"+ + "\2\0\12\7\1\0\2\6\17\0\2\7\1\0\10\6\1\0\3\6"+ + "\1\0\51\6\2\0\1\6\7\7\1\0\3\7\1\0\4\7\1\6"+ + "\10\0\1\7\10\0\2\6\2\7\2\0\12\7\12\0\6\6\2\0"+ + "\2\7\1\0\22\6\3\0\30\6\1\0\11\6\1\0\1\6\2\0"+ + "\7\6\3\0\1\7\4\0\6\7\1\0\1\7\1\0\10\7\22\0"+ + "\2\7\15\0\60\6\1\7\2\6\7\7\4\0\10\6\10\7\1\0"+ + "\12\7\47\0\2\6\1\0\1\6\2\0\2\6\1\0\1\6\2\0"+ + "\1\6\6\0\4\6\1\0\7\6\1\0\3\6\1\0\1\6\1\0"+ + "\1\6\2\0\2\6\1\0\4\6\1\7\2\6\6\7\1\0\2\7"+ + "\1\6\2\0\5\6\1\0\1\6\1\0\6\7\2\0\12\7\2\0"+ + "\4\6\40\0\1\6\27\0\2\7\6\0\12\7\13\0\1\7\1\0"+ + "\1\7\1\0\1\7\4\0\2\7\10\6\1\0\44\6\4\0\24\7"+ + "\1\0\2\7\5\6\13\7\1\0\44\7\11\0\1\7\71\0\53\6"+ + "\24\7\1\6\12\7\6\0\6\6\4\7\4\6\3\7\1\6\3\7"+ + "\2\6\7\7\3\6\4\7\15\6\14\7\1\6\17\7\2\0\46\6"+ + "\1\0\1\6\5\0\1\6\2\0\53\6\1\0\u014d\6\1\0\4\6"+ + "\2\0\7\6\1\0\1\6\1\0\4\6\2\0\51\6\1\0\4\6"+ + "\2\0\41\6\1\0\4\6\2\0\7\6\1\0\1\6\1\0\4\6"+ + "\2\0\17\6\1\0\71\6\1\0\4\6\2\0\103\6\2\0\3\7"+ + "\40\0\20\6\20\0\125\6\14\0\u026c\6\2\0\21\6\1\0\32\6"+ + "\5\0\113\6\3\0\3\6\17\0\15\6\1\0\4\6\3\7\13\0"+ + "\22\6\3\7\13\0\22\6\2\7\14\0\15\6\1\0\3\6\1\0"+ + "\2\7\14\0\64\6\40\7\3\0\1\6\3\0\2\6\1\7\2\0"+ + "\12\7\41\0\3\7\2\0\12\7\6\0\130\6\10\0\51\6\1\7"+ + "\1\6\5\0\106\6\12\0\35\6\3\0\14\7\4\0\14\7\12\0"+ + "\12\7\36\6\2\0\5\6\13\0\54\6\4\0\21\7\7\6\2\7"+ + "\6\0\12\7\46\0\27\6\5\7\4\0\65\6\12\7\1\0\35\7"+ + "\2\0\13\7\6\0\12\7\15\0\1\6\130\0\5\7\57\6\21\7"+ + "\7\6\4\0\12\7\21\0\11\7\14\0\3\7\36\6\15\7\2\6"+ + "\12\7\54\6\16\7\14\0\44\6\24\7\10\0\12\7\3\0\3\6"+ + "\12\7\44\6\122\0\3\7\1\0\25\7\4\6\1\7\4\6\3\7"+ + "\2\6\11\0\300\6\47\7\25\0\4\7\u0116\6\2\0\6\6\2\0"+ + "\46\6\2\0\6\6\2\0\10\6\1\0\1\6\1\0\1\6\1\0"+ + "\1\6\1\0\37\6\2\0\65\6\1\0\7\6\1\0\1\6\3\0"+ + "\3\6\1\0\7\6\3\0\4\6\2\0\6\6\4\0\15\6\5\0"+ + "\3\6\1\0\7\6\16\0\5\7\30\0\1\121\1\121\5\7\20\0"+ + "\2\6\23\0\1\6\13\0\5\7\5\0\6\7\1\0\1\6\15\0"+ + "\1\6\20\0\15\6\3\0\33\6\25\0\15\7\4\0\1\7\3\0"+ + "\14\7\21\0\1\6\4\0\1\6\2\0\12\6\1\0\1\6\3\0"+ + "\5\6\6\0\1\6\1\0\1\6\1\0\1\6\1\0\4\6\1\0"+ + "\13\6\2\0\4\6\5\0\5\6\4\0\1\6\21\0\51\6\u0a77\0"+ + "\57\6\1\0\57\6\1\0\205\6\6\0\4\6\3\7\2\6\14\0"+ + "\46\6\1\0\1\6\5\0\1\6\2\0\70\6\7\0\1\6\17\0"+ + "\1\7\27\6\11\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6"+ + "\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6\1\0\40\7"+ + "\57\0\1\6\u01d5\0\3\6\31\0\11\6\6\7\1\0\5\6\2\0"+ + "\5\6\4\0\126\6\2\0\2\7\2\0\3\6\1\0\132\6\1\0"+ + "\4\6\5\0\51\6\3\0\136\6\21\0\33\6\65\0\20\6\u0200\0"+ + "\u19b6\6\112\0\u51cd\6\63\0\u048d\6\103\0\56\6\2\0\u010d\6\3\0"+ + "\20\6\12\7\2\6\24\0\57\6\1\7\4\0\12\7\1\0\31\6"+ + "\7\0\1\7\120\6\2\7\45\0\11\6\2\0\147\6\2\0\4\6"+ + "\1\0\4\6\14\0\13\6\115\0\12\6\1\7\3\6\1\7\4\6"+ + "\1\7\27\6\5\7\20\0\1\6\7\0\64\6\14\0\2\7\62\6"+ + "\21\7\13\0\12\7\6\0\22\7\6\6\3\0\1\6\4\0\12\7"+ + "\34\6\10\7\2\0\27\6\15\7\14\0\35\6\3\0\4\7\57\6"+ + "\16\7\16\0\1\6\12\7\46\0\51\6\16\7\11\0\3\6\1\7"+ + "\10\6\2\7\2\0\12\7\6\0\27\6\3\0\1\6\1\7\4\0"+ + "\60\6\1\7\1\6\3\7\2\6\2\7\5\6\2\7\1\6\1\7"+ + "\1\6\30\0\3\6\2\0\13\6\5\7\2\0\3\6\2\7\12\0"+ + "\6\6\2\0\6\6\2\0\6\6\11\0\7\6\1\0\7\6\221\0"+ + "\43\6\10\7\1\0\2\7\2\0\12\7\6\0\u2ba4\6\14\0\27\6"+ + "\4\0\61\6\u2104\0\u016e\6\2\0\152\6\46\0\7\6\14\0\5\6"+ + "\5\0\1\6\1\7\12\6\1\0\15\6\1\0\5\6\1\0\1\6"+ + "\1\0\2\6\1\0\2\6\1\0\154\6\41\0\u016b\6\22\0\100\6"+ + "\2\0\66\6\50\0\15\6\3\0\20\7\20\0\7\7\14\0\2\6"+ + "\30\0\3\6\31\0\1\6\6\0\5\6\1\0\207\6\2\0\1\7"+ + "\4\0\1\6\13\0\12\7\7\0\32\6\4\0\1\6\1\0\32\6"+ + "\13\0\131\6\3\0\6\6\2\0\6\6\2\0\6\6\2\0\3\6"+ + "\3\0\2\6\3\0\2\6\22\0\3\7\4\0\14\6\1\0\32\6"+ + "\1\0\23\6\1\0\2\6\1\0\17\6\2\0\16\6\42\0\173\6"+ + "\105\0\65\6\210\0\1\7\202\0\35\6\3\0\61\6\57\0\37\6"+ + "\21\0\33\6\65\0\36\6\2\0\44\6\4\0\10\6\1\0\5\6"+ + "\52\0\236\6\2\0\12\7\u0356\0\6\6\2\0\1\6\1\0\54\6"+ + "\1\0\2\6\3\0\1\6\2\0\27\6\252\0\26\6\12\0\32\6"+ + "\106\0\70\6\6\0\2\6\100\0\1\6\3\7\1\0\2\7\5\0"+ + "\4\7\4\6\1\0\3\6\1\0\33\6\4\0\3\7\4\0\1\7"+ + "\40\0\35\6\203\0\66\6\12\0\26\6\12\0\23\6\215\0\111\6"+ + "\u03b7\0\3\7\65\6\17\7\37\0\12\7\20\0\3\7\55\6\13\7"+ + "\2\0\1\7\22\0\31\6\7\0\12\7\6\0\3\7\44\6\16\7"+ + "\1\0\12\7\100\0\3\7\60\6\16\7\4\6\13\0\12\7\u04a6\0"+ + "\53\6\15\7\10\0\12\7\u0936\0\u036f\6\221\0\143\6\u0b9d\0\u042f\6"+ + "\u33d1\0\u0239\6\u04c7\0\105\6\13\0\1\6\56\7\20\0\4\7\15\6"+ + "\u4060\0\2\6\u2163\0\5\7\3\0\26\7\2\0\7\7\36\0\4\7"+ + "\224\0\3\7\u01bb\0\125\6\1\0\107\6\1\0\2\6\2\0\1\6"+ + "\2\0\2\6\2\0\4\6\1\0\14\6\1\0\1\6\1\0\7\6"+ + "\1\0\101\6\1\0\4\6\2\0\10\6\1\0\7\6\1\0\34\6"+ + "\1\0\4\6\1\0\5\6\1\0\1\6\3\0\7\6\1\0\u0154\6"+ + "\2\0\31\6\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6"+ + "\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6\1\0\31\6"+ + "\1\0\10\6\2\0\62\7\u1600\0\4\6\1\0\33\6\1\0\2\6"+ + "\1\0\1\6\2\0\1\6\1\0\12\6\1\0\4\6\1\0\1\6"+ + "\1\0\1\6\6\0\1\6\4\0\1\6\1\0\1\6\1\0\1\6"+ + "\1\0\3\6\1\0\2\6\1\0\1\6\2\0\1\6\1\0\1\6"+ + "\1\0\1\6\1\0\1\6\1\0\1\6\1\0\2\6\1\0\1\6"+ + "\2\0\4\6\1\0\7\6\1\0\4\6\1\0\4\6\1\0\1\6"+ + "\1\0\12\6\1\0\21\6\5\0\3\6\1\0\5\6\1\0\21\6"+ + "\u1144\0\ua6d7\6\51\0\u1035\6\13\0\336\6\u3fe2\0\u021e\6\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\u05ee\0"+ + "\1\7\36\0\140\7\200\0\360\7\uffff\0\uffff\0\ufe12\0"; - public static final int XMLSTARTTAG = 6; + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - public static final int XML = 8; + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); - public static final int OIDENTIFIER = 10; + private static final String ZZ_ACTION_PACKED_0 = + "\6\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7"+ + "\1\10\1\11\1\12\1\13\1\14\2\15\1\16\1\17"+ + "\1\20\26\6\1\21\1\22\1\23\1\24\1\25\1\26"+ + "\1\27\1\30\1\31\1\32\1\33\1\34\1\35\1\36"+ + "\1\37\1\40\1\41\1\42\2\43\1\44\1\1\1\42"+ + "\1\1\2\45\1\42\1\1\1\46\2\42\2\47\2\42"+ + "\1\1\1\50\1\3\1\0\1\51\1\52\1\53\2\0"+ + "\1\54\1\0\1\55\1\56\1\57\1\60\1\61\1\62"+ + "\1\63\1\54\1\0\2\63\1\0\1\64\1\65\1\0"+ + "\7\6\1\66\11\6\1\67\12\6\1\70\1\71\1\72"+ + "\4\6\1\73\30\6\1\56\1\74\1\75\1\76\1\77"+ + "\1\100\1\101\1\102\1\103\1\104\1\105\1\104\1\106"+ + "\1\107\1\110\1\111\1\112\1\113\1\104\1\114\1\104"+ + "\6\0\1\115\1\116\2\115\2\3\2\0\1\117\3\0"+ + "\1\120\1\0\1\121\1\122\1\123\1\124\2\125\1\63"+ + "\1\54\1\0\1\126\10\6\1\127\5\6\1\130\1\131"+ + "\5\6\1\132\1\6\1\133\5\6\1\134\7\6\1\135"+ + "\2\6\1\136\10\6\1\137\20\6\1\140\1\6\1\141"+ + "\2\6\1\142\2\6\1\143\12\0\1\144\5\0\1\145"+ + "\1\125\1\63\4\6\1\146\1\147\1\150\1\6\1\151"+ + "\1\6\1\152\5\6\1\153\7\6\1\154\1\6\1\155"+ + "\4\6\1\156\22\6\1\157\7\6\1\160\4\6\1\161"+ + "\7\6\1\162\1\0\1\163\1\42\1\0\1\164\12\0"+ + "\1\125\1\63\1\165\4\6\1\166\1\167\1\6\1\170"+ + "\5\6\1\171\5\6\1\172\3\6\1\173\14\6\1\174"+ + "\6\6\1\175\2\6\1\176\3\6\1\177\1\6\1\200"+ + "\10\6\10\0\1\125\1\63\1\201\1\6\1\202\3\6"+ + "\1\203\2\6\1\204\1\205\7\6\1\206\4\6\1\207"+ + "\4\6\1\210\5\6\1\211\10\6\1\212\2\6\1\213"+ + "\3\6\1\214\1\215\1\6\2\0\1\120\1\125\1\63"+ + "\1\6\1\216\5\6\1\217\14\6\1\220\1\6\1\221"+ + "\1\6\1\222\7\6\1\223\1\224\6\6\1\42\1\125"+ + "\1\63\1\6\1\225\2\6\1\226\1\227\6\6\1\230"+ + "\7\6\1\231\5\6\1\232\1\6\1\233\1\234\3\6"+ + "\1\235\1\125\1\63\1\6\1\236\1\6\1\237\1\240"+ + "\4\6\1\241\2\6\1\242\2\6\1\243\1\244\1\6"+ + "\1\245\1\246\5\6\1\125\1\63\2\6\1\247\1\250"+ + "\1\6\1\251\1\6\1\252\6\6\1\253\2\6\1\63"+ + "\4\6\1\254\4\6\1\255\1\256\1\257\1\63\6\6"+ + "\1\260\2\6\1\63\1\6\1\261\1\6\1\262\2\6"+ + "\1\263\1\264\1\63\2\6\1\265\3\6\1\63\1\266"+ + "\4\6\1\63\2\6\1\267\1\270\1\271\1\6\1\272"; - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the - * beginning of a line l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 - }; + private static int [] zzUnpackAction() { + int [] result = new int[707]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED - = "\11\7\1\3\1\2\1\121\1\122\1\1\16\7\4\0\1\14\1\110" - + "\1\16\1\0\1\6\1\117\1\113\1\30\1\100\1\101\1\5\1\115" - + "\1\107\1\26\1\11\1\4\1\17\3\23\4\24\2\20\1\10\1\106" - + "\1\12\1\15\1\13\1\112\1\120\1\62\1\22\1\72\1\73\1\25" - + "\1\64\1\6\1\66\1\77\2\6\1\70\1\71\1\76\1\6\1\75" - + "\1\67\1\6\1\63\1\65\1\61\1\74\1\6\1\21\2\6\1\104" - + "\1\27\1\105\1\116\1\6\1\0\1\35\1\32\1\37\1\46\1\34" - + "\1\47\1\60\1\52\1\44\1\6\1\36\1\50\1\55\1\42\1\41" - + "\1\53\1\6\1\33\1\40\1\43\1\45\1\56\1\51\1\57\1\54" - + "\1\6\1\102\1\114\1\103\1\111\6\7\1\123\32\7\2\0\4\6" - + "\1\0\1\31\2\0\1\6\2\0\1\7\7\0\1\6\4\0\1\6" - + "\5\0\27\6\1\0\37\6\1\0\u01ca\6\4\0\14\6\16\0\5\6" - + "\7\0\1\6\1\0\1\6\21\0\160\7\5\6\1\0\2\6\2\0" - + "\4\6\10\0\1\6\1\0\3\6\1\0\1\6\1\0\24\6\1\0" - + "\123\6\1\0\213\6\1\0\5\7\2\0\236\6\11\0\46\6\2\0" - + "\1\6\7\0\47\6\7\0\1\6\1\0\55\7\1\0\1\7\1\0" - + "\2\7\1\0\2\7\1\0\1\7\10\0\33\6\5\0\3\6\15\0" - + "\5\7\6\0\1\6\4\0\13\7\5\0\53\6\37\7\4\0\2\6" - + "\1\7\143\6\1\0\1\6\10\7\1\0\6\7\2\6\2\7\1\0" - + "\4\7\2\6\12\7\3\6\2\0\1\6\17\0\1\7\1\6\1\7" - + "\36\6\33\7\2\0\131\6\13\7\1\6\16\0\12\7\41\6\11\7" - + "\2\6\4\0\1\6\5\0\26\6\4\7\1\6\11\7\1\6\3\7" - + "\1\6\5\7\22\0\31\6\3\7\104\0\1\6\1\0\13\6\67\0" - + "\33\7\1\0\4\7\66\6\3\7\1\6\22\7\1\6\7\7\12\6" - + "\2\7\2\0\12\7\1\0\7\6\1\0\7\6\1\0\3\7\1\0" - + "\10\6\2\0\2\6\2\0\26\6\1\0\7\6\1\0\1\6\3\0" - + "\4\6\2\0\1\7\1\6\7\7\2\0\2\7\2\0\3\7\1\6" - + "\10\0\1\7\4\0\2\6\1\0\3\6\2\7\2\0\12\7\4\6" - + "\7\0\1\6\5\0\3\7\1\0\6\6\4\0\2\6\2\0\26\6" - + "\1\0\7\6\1\0\2\6\1\0\2\6\1\0\2\6\2\0\1\7" - + "\1\0\5\7\4\0\2\7\2\0\3\7\3\0\1\7\7\0\4\6" - + "\1\0\1\6\7\0\14\7\3\6\1\7\13\0\3\7\1\0\11\6" - + "\1\0\3\6\1\0\26\6\1\0\7\6\1\0\2\6\1\0\5\6" - + "\2\0\1\7\1\6\10\7\1\0\3\7\1\0\3\7\2\0\1\6" - + "\17\0\2\6\2\7\2\0\12\7\1\0\1\6\17\0\3\7\1\0" - + "\10\6\2\0\2\6\2\0\26\6\1\0\7\6\1\0\2\6\1\0" - + "\5\6\2\0\1\7\1\6\7\7\2\0\2\7\2\0\3\7\10\0" - + "\2\7\4\0\2\6\1\0\3\6\2\7\2\0\12\7\1\0\1\6" - + "\20\0\1\7\1\6\1\0\6\6\3\0\3\6\1\0\4\6\3\0" - + "\2\6\1\0\1\6\1\0\2\6\3\0\2\6\3\0\3\6\3\0" - + "\14\6\4\0\5\7\3\0\3\7\1\0\4\7\2\0\1\6\6\0" - + "\1\7\16\0\12\7\11\0\1\6\7\0\3\7\1\0\10\6\1\0" - + "\3\6\1\0\27\6\1\0\12\6\1\0\5\6\3\0\1\6\7\7" - + "\1\0\3\7\1\0\4\7\7\0\2\7\1\0\2\6\6\0\2\6" - + "\2\7\2\0\12\7\22\0\2\7\1\0\10\6\1\0\3\6\1\0" - + "\27\6\1\0\12\6\1\0\5\6\2\0\1\7\1\6\7\7\1\0" - + "\3\7\1\0\4\7\7\0\2\7\7\0\1\6\1\0\2\6\2\7" - + "\2\0\12\7\1\0\2\6\17\0\2\7\1\0\10\6\1\0\3\6" - + "\1\0\51\6\2\0\1\6\7\7\1\0\3\7\1\0\4\7\1\6" - + "\10\0\1\7\10\0\2\6\2\7\2\0\12\7\12\0\6\6\2\0" - + "\2\7\1\0\22\6\3\0\30\6\1\0\11\6\1\0\1\6\2\0" - + "\7\6\3\0\1\7\4\0\6\7\1\0\1\7\1\0\10\7\22\0" - + "\2\7\15\0\60\6\1\7\2\6\7\7\4\0\10\6\10\7\1\0" - + "\12\7\47\0\2\6\1\0\1\6\2\0\2\6\1\0\1\6\2\0" - + "\1\6\6\0\4\6\1\0\7\6\1\0\3\6\1\0\1\6\1\0" - + "\1\6\2\0\2\6\1\0\4\6\1\7\2\6\6\7\1\0\2\7" - + "\1\6\2\0\5\6\1\0\1\6\1\0\6\7\2\0\12\7\2\0" - + "\4\6\40\0\1\6\27\0\2\7\6\0\12\7\13\0\1\7\1\0" - + "\1\7\1\0\1\7\4\0\2\7\10\6\1\0\44\6\4\0\24\7" - + "\1\0\2\7\5\6\13\7\1\0\44\7\11\0\1\7\71\0\53\6" - + "\24\7\1\6\12\7\6\0\6\6\4\7\4\6\3\7\1\6\3\7" - + "\2\6\7\7\3\6\4\7\15\6\14\7\1\6\17\7\2\0\46\6" - + "\1\0\1\6\5\0\1\6\2\0\53\6\1\0\u014d\6\1\0\4\6" - + "\2\0\7\6\1\0\1\6\1\0\4\6\2\0\51\6\1\0\4\6" - + "\2\0\41\6\1\0\4\6\2\0\7\6\1\0\1\6\1\0\4\6" - + "\2\0\17\6\1\0\71\6\1\0\4\6\2\0\103\6\2\0\3\7" - + "\40\0\20\6\20\0\125\6\14\0\u026c\6\2\0\21\6\1\0\32\6" - + "\5\0\113\6\3\0\3\6\17\0\15\6\1\0\4\6\3\7\13\0" - + "\22\6\3\7\13\0\22\6\2\7\14\0\15\6\1\0\3\6\1\0" - + "\2\7\14\0\64\6\40\7\3\0\1\6\3\0\2\6\1\7\2\0" - + "\12\7\41\0\3\7\2\0\12\7\6\0\130\6\10\0\51\6\1\7" - + "\1\6\5\0\106\6\12\0\35\6\3\0\14\7\4\0\14\7\12\0" - + "\12\7\36\6\2\0\5\6\13\0\54\6\4\0\21\7\7\6\2\7" - + "\6\0\12\7\46\0\27\6\5\7\4\0\65\6\12\7\1\0\35\7" - + "\2\0\13\7\6\0\12\7\15\0\1\6\130\0\5\7\57\6\21\7" - + "\7\6\4\0\12\7\21\0\11\7\14\0\3\7\36\6\15\7\2\6" - + "\12\7\54\6\16\7\14\0\44\6\24\7\10\0\12\7\3\0\3\6" - + "\12\7\44\6\122\0\3\7\1\0\25\7\4\6\1\7\4\6\3\7" - + "\2\6\11\0\300\6\47\7\25\0\4\7\u0116\6\2\0\6\6\2\0" - + "\46\6\2\0\6\6\2\0\10\6\1\0\1\6\1\0\1\6\1\0" - + "\1\6\1\0\37\6\2\0\65\6\1\0\7\6\1\0\1\6\3\0" - + "\3\6\1\0\7\6\3\0\4\6\2\0\6\6\4\0\15\6\5\0" - + "\3\6\1\0\7\6\16\0\5\7\30\0\1\121\1\121\5\7\20\0" - + "\2\6\23\0\1\6\13\0\5\7\5\0\6\7\1\0\1\6\15\0" - + "\1\6\20\0\15\6\3\0\33\6\25\0\15\7\4\0\1\7\3\0" - + "\14\7\21\0\1\6\4\0\1\6\2\0\12\6\1\0\1\6\3\0" - + "\5\6\6\0\1\6\1\0\1\6\1\0\1\6\1\0\4\6\1\0" - + "\13\6\2\0\4\6\5\0\5\6\4\0\1\6\21\0\51\6\u0a77\0" - + "\57\6\1\0\57\6\1\0\205\6\6\0\4\6\3\7\2\6\14\0" - + "\46\6\1\0\1\6\5\0\1\6\2\0\70\6\7\0\1\6\17\0" - + "\1\7\27\6\11\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6" - + "\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6\1\0\40\7" - + "\57\0\1\6\u01d5\0\3\6\31\0\11\6\6\7\1\0\5\6\2\0" - + "\5\6\4\0\126\6\2\0\2\7\2\0\3\6\1\0\132\6\1\0" - + "\4\6\5\0\51\6\3\0\136\6\21\0\33\6\65\0\20\6\u0200\0" - + "\u19b6\6\112\0\u51cd\6\63\0\u048d\6\103\0\56\6\2\0\u010d\6\3\0" - + "\20\6\12\7\2\6\24\0\57\6\1\7\4\0\12\7\1\0\31\6" - + "\7\0\1\7\120\6\2\7\45\0\11\6\2\0\147\6\2\0\4\6" - + "\1\0\4\6\14\0\13\6\115\0\12\6\1\7\3\6\1\7\4\6" - + "\1\7\27\6\5\7\20\0\1\6\7\0\64\6\14\0\2\7\62\6" - + "\21\7\13\0\12\7\6\0\22\7\6\6\3\0\1\6\4\0\12\7" - + "\34\6\10\7\2\0\27\6\15\7\14\0\35\6\3\0\4\7\57\6" - + "\16\7\16\0\1\6\12\7\46\0\51\6\16\7\11\0\3\6\1\7" - + "\10\6\2\7\2\0\12\7\6\0\27\6\3\0\1\6\1\7\4\0" - + "\60\6\1\7\1\6\3\7\2\6\2\7\5\6\2\7\1\6\1\7" - + "\1\6\30\0\3\6\2\0\13\6\5\7\2\0\3\6\2\7\12\0" - + "\6\6\2\0\6\6\2\0\6\6\11\0\7\6\1\0\7\6\221\0" - + "\43\6\10\7\1\0\2\7\2\0\12\7\6\0\u2ba4\6\14\0\27\6" - + "\4\0\61\6\u2104\0\u016e\6\2\0\152\6\46\0\7\6\14\0\5\6" - + "\5\0\1\6\1\7\12\6\1\0\15\6\1\0\5\6\1\0\1\6" - + "\1\0\2\6\1\0\2\6\1\0\154\6\41\0\u016b\6\22\0\100\6" - + "\2\0\66\6\50\0\15\6\3\0\20\7\20\0\7\7\14\0\2\6" - + "\30\0\3\6\31\0\1\6\6\0\5\6\1\0\207\6\2\0\1\7" - + "\4\0\1\6\13\0\12\7\7\0\32\6\4\0\1\6\1\0\32\6" - + "\13\0\131\6\3\0\6\6\2\0\6\6\2\0\6\6\2\0\3\6" - + "\3\0\2\6\3\0\2\6\22\0\3\7\4\0\14\6\1\0\32\6" - + "\1\0\23\6\1\0\2\6\1\0\17\6\2\0\16\6\42\0\173\6" - + "\105\0\65\6\210\0\1\7\202\0\35\6\3\0\61\6\57\0\37\6" - + "\21\0\33\6\65\0\36\6\2\0\44\6\4\0\10\6\1\0\5\6" - + "\52\0\236\6\2\0\12\7\u0356\0\6\6\2\0\1\6\1\0\54\6" - + "\1\0\2\6\3\0\1\6\2\0\27\6\252\0\26\6\12\0\32\6" - + "\106\0\70\6\6\0\2\6\100\0\1\6\3\7\1\0\2\7\5\0" - + "\4\7\4\6\1\0\3\6\1\0\33\6\4\0\3\7\4\0\1\7" - + "\40\0\35\6\203\0\66\6\12\0\26\6\12\0\23\6\215\0\111\6" - + "\u03b7\0\3\7\65\6\17\7\37\0\12\7\20\0\3\7\55\6\13\7" - + "\2\0\1\7\22\0\31\6\7\0\12\7\6\0\3\7\44\6\16\7" - + "\1\0\12\7\100\0\3\7\60\6\16\7\4\6\13\0\12\7\u04a6\0" - + "\53\6\15\7\10\0\12\7\u0936\0\u036f\6\221\0\143\6\u0b9d\0\u042f\6" - + "\u33d1\0\u0239\6\u04c7\0\105\6\13\0\1\6\56\7\20\0\4\7\15\6" - + "\u4060\0\2\6\u2163\0\5\7\3\0\26\7\2\0\7\7\36\0\4\7" - + "\224\0\3\7\u01bb\0\125\6\1\0\107\6\1\0\2\6\2\0\1\6" - + "\2\0\2\6\2\0\4\6\1\0\14\6\1\0\1\6\1\0\7\6" - + "\1\0\101\6\1\0\4\6\2\0\10\6\1\0\7\6\1\0\34\6" - + "\1\0\4\6\1\0\5\6\1\0\1\6\3\0\7\6\1\0\u0154\6" - + "\2\0\31\6\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6" - + "\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6\1\0\31\6" - + "\1\0\10\6\2\0\62\7\u1600\0\4\6\1\0\33\6\1\0\2\6" - + "\1\0\1\6\2\0\1\6\1\0\12\6\1\0\4\6\1\0\1\6" - + "\1\0\1\6\6\0\1\6\4\0\1\6\1\0\1\6\1\0\1\6" - + "\1\0\3\6\1\0\2\6\1\0\1\6\2\0\1\6\1\0\1\6" - + "\1\0\1\6\1\0\1\6\1\0\1\6\1\0\2\6\1\0\1\6" - + "\2\0\4\6\1\0\7\6\1\0\4\6\1\0\4\6\1\0\1\6" - + "\1\0\12\6\1\0\21\6\5\0\3\6\1\0\5\6\1\0\21\6" - + "\u1144\0\ua6d7\6\51\0\u1035\6\13\0\336\6\u3fe2\0\u021e\6\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\u05ee\0" - + "\1\7\36\0\140\7\200\0\360\7\uffff\0\uffff\0\ufe12\0"; - - /** - * Translates characters to character classes - */ - private static final char[] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int[] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 - = "\6\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7" - + "\1\10\1\11\1\12\1\13\1\14\2\15\1\16\1\17" - + "\1\20\26\6\1\21\1\22\1\23\1\24\1\25\1\26" - + "\1\27\1\30\1\31\1\32\1\33\1\34\1\35\1\36" - + "\1\37\1\40\1\41\1\42\2\43\1\44\1\1\1\42" - + "\1\1\2\45\1\42\1\1\1\46\2\42\2\47\2\42" - + "\1\1\1\50\1\3\1\0\1\51\1\52\1\53\2\0" - + "\1\54\1\0\1\55\1\56\1\57\1\60\1\61\1\62" - + "\1\63\1\54\1\0\2\63\1\0\1\64\1\65\7\6" - + "\1\66\11\6\1\67\12\6\1\70\1\71\1\72\4\6" - + "\1\73\30\6\1\56\1\74\1\75\1\76\1\77\1\100" - + "\1\101\1\102\1\103\1\104\1\105\1\104\1\106\1\107" - + "\1\110\1\111\1\112\1\113\1\104\1\114\1\104\6\0" - + "\1\115\1\116\2\115\2\3\2\0\1\117\3\0\1\120" - + "\1\0\1\121\1\122\1\123\1\124\2\125\1\63\1\54" - + "\1\0\10\6\1\126\5\6\1\127\1\130\5\6\1\131" - + "\1\6\1\132\5\6\1\133\7\6\1\134\2\6\1\135" - + "\10\6\1\136\20\6\1\137\1\6\1\140\2\6\1\141" - + "\2\6\1\142\12\0\1\143\5\0\1\144\1\125\1\63" - + "\4\6\1\145\1\146\1\147\1\6\1\150\1\6\1\151" - + "\5\6\1\152\7\6\1\153\1\6\1\154\4\6\1\155" - + "\22\6\1\156\7\6\1\157\4\6\1\160\7\6\1\161" - + "\1\0\1\162\1\42\1\0\1\163\12\0\1\125\1\63" - + "\1\164\4\6\1\165\1\166\1\6\1\167\5\6\1\170" - + "\5\6\1\171\3\6\1\172\14\6\1\173\6\6\1\174" - + "\2\6\1\175\3\6\1\176\1\6\1\177\10\6\10\0" - + "\1\125\1\63\1\200\1\6\1\201\3\6\1\202\2\6" - + "\1\203\1\204\7\6\1\205\4\6\1\206\4\6\1\207" - + "\5\6\1\210\10\6\1\211\2\6\1\212\3\6\1\213" - + "\1\214\1\6\2\0\1\120\1\125\1\63\1\6\1\215" - + "\5\6\1\216\14\6\1\217\1\6\1\220\1\6\1\221" - + "\7\6\1\222\1\223\6\6\1\42\1\125\1\63\1\6" - + "\1\224\2\6\1\225\1\226\6\6\1\227\7\6\1\230" - + "\5\6\1\231\1\6\1\232\1\233\3\6\1\234\1\125" - + "\1\63\1\6\1\235\1\6\1\236\1\237\4\6\1\240" - + "\2\6\1\241\2\6\1\242\1\243\1\6\1\244\1\245" - + "\5\6\1\125\1\63\2\6\1\246\1\247\1\6\1\250" - + "\1\6\1\251\6\6\1\252\2\6\1\63\4\6\1\253" - + "\4\6\1\254\1\255\1\256\1\63\6\6\1\257\2\6" - + "\1\63\1\6\1\260\1\6\1\261\2\6\1\262\1\263" - + "\1\63\2\6\1\264\3\6\1\63\1\265\4\6\1\63" - + "\2\6\1\266\1\267\1\270\1\6\1\271"; - - private static int[] zzUnpackAction() { - int[] result = new int[705]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); } + return j; + } - private static int zzUnpackAction(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do { - result[j++] = value; - } while (--count > 0); - } - return j; + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\124\0\250\0\374\0\u0150\0\u01a4\0\u01f8\0\u024c"+ + "\0\u01f8\0\u02a0\0\u02f4\0\u0348\0\u039c\0\u03f0\0\u0444\0\u0498"+ + "\0\u04ec\0\u0540\0\u01f8\0\u0594\0\u05e8\0\u063c\0\u01f8\0\u0690"+ + "\0\u06e4\0\u0738\0\u078c\0\u07e0\0\u0834\0\u0888\0\u08dc\0\u0930"+ + "\0\u0984\0\u09d8\0\u0a2c\0\u0a80\0\u0ad4\0\u0b28\0\u0b7c\0\u0bd0"+ + "\0\u0c24\0\u0c78\0\u0ccc\0\u0d20\0\u0d74\0\u0dc8\0\u01f8\0\u01f8"+ + "\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u0e1c\0\u01f8"+ + "\0\u01f8\0\u0e70\0\u0ec4\0\u0f18\0\u0f6c\0\u0fc0\0\u01f8\0\u1014"+ + "\0\u1068\0\u01f8\0\u01f8\0\u10bc\0\u1110\0\u1164\0\u11b8\0\u01f8"+ + "\0\u120c\0\u1260\0\u01f8\0\u12b4\0\u01f8\0\u1308\0\u01f8\0\u135c"+ + "\0\u13b0\0\u1404\0\u01f8\0\u1458\0\u14ac\0\u01f8\0\u01f8\0\u01f8"+ + "\0\u1500\0\u1554\0\u15a8\0\u15fc\0\u1650\0\u01f8\0\u01f8\0\u16a4"+ + "\0\u01f8\0\u16f8\0\u174c\0\u17a0\0\u17f4\0\u1848\0\u189c\0\u18f0"+ + "\0\u01f8\0\u01f8\0\u1944\0\u1998\0\u19ec\0\u1a40\0\u1a94\0\u1ae8"+ + "\0\u1b3c\0\u1b90\0\u039c\0\u1be4\0\u1c38\0\u1c8c\0\u1ce0\0\u1d34"+ + "\0\u1d88\0\u1ddc\0\u1e30\0\u1e84\0\u1ed8\0\u1f2c\0\u1f80\0\u1fd4"+ + "\0\u2028\0\u207c\0\u20d0\0\u2124\0\u2178\0\u21cc\0\u2220\0\u039c"+ + "\0\u2274\0\u22c8\0\u231c\0\u2370\0\u23c4\0\u2418\0\u039c\0\u246c"+ + "\0\u24c0\0\u2514\0\u2568\0\u25bc\0\u2610\0\u2664\0\u26b8\0\u270c"+ + "\0\u2760\0\u27b4\0\u2808\0\u285c\0\u28b0\0\u2904\0\u2958\0\u29ac"+ + "\0\u2a00\0\u2a54\0\u2aa8\0\u2afc\0\u2b50\0\u2ba4\0\u2bf8\0\u2c4c"+ + "\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8"+ + "\0\u01f8\0\u01f8\0\u2ca0\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8"+ + "\0\u01f8\0\u2cf4\0\u01f8\0\u2d48\0\u1260\0\u2d9c\0\u2df0\0\u2e44"+ + "\0\u2e98\0\u2eec\0\u01f8\0\u01f8\0\u2cf4\0\u2d48\0\u2f40\0\u01f8"+ + "\0\u2f94\0\u2fe8\0\u01f8\0\u303c\0\u3090\0\u30e4\0\u01f8\0\u3138"+ + "\0\u01f8\0\u318c\0\u01f8\0\u01f8\0\u17f4\0\u31e0\0\u3234\0\u3288"+ + "\0\u3288\0\u32dc\0\u3330\0\u3384\0\u33d8\0\u342c\0\u3480\0\u34d4"+ + "\0\u3528\0\u357c\0\u039c\0\u35d0\0\u3624\0\u3678\0\u36cc\0\u3720"+ + "\0\u039c\0\u039c\0\u3774\0\u37c8\0\u381c\0\u3870\0\u38c4\0\u039c"+ + "\0\u3918\0\u396c\0\u39c0\0\u3a14\0\u3a68\0\u3abc\0\u3b10\0\u039c"+ + "\0\u3b64\0\u3bb8\0\u3c0c\0\u3c60\0\u3cb4\0\u3d08\0\u3d5c\0\u3db0"+ + "\0\u3e04\0\u3e58\0\u039c\0\u3eac\0\u3f00\0\u3f54\0\u3fa8\0\u3ffc"+ + "\0\u4050\0\u40a4\0\u40f8\0\u039c\0\u414c\0\u41a0\0\u41f4\0\u4248"+ + "\0\u429c\0\u42f0\0\u4344\0\u4398\0\u43ec\0\u4440\0\u4494\0\u44e8"+ + "\0\u453c\0\u4590\0\u45e4\0\u4638\0\u039c\0\u468c\0\u46e0\0\u4734"+ + "\0\u4788\0\u039c\0\u47dc\0\u4830\0\u01f8\0\u4884\0\u48d8\0\u492c"+ + "\0\u4980\0\u49d4\0\u4a28\0\u4a7c\0\u4ad0\0\u4b24\0\u4b78\0\u01f8"+ + "\0\u4bcc\0\u4c20\0\u4c74\0\u4cc8\0\u4d1c\0\u01f8\0\u4d70\0\u4dc4"+ + "\0\u4e18\0\u4e6c\0\u4ec0\0\u4f14\0\u039c\0\u039c\0\u039c\0\u4f68"+ + "\0\u039c\0\u4fbc\0\u039c\0\u5010\0\u5064\0\u50b8\0\u510c\0\u5160"+ + "\0\u51b4\0\u5208\0\u525c\0\u52b0\0\u5304\0\u5358\0\u53ac\0\u5400"+ + "\0\u039c\0\u5454\0\u039c\0\u54a8\0\u54fc\0\u5550\0\u55a4\0\u039c"+ + "\0\u55f8\0\u564c\0\u56a0\0\u56f4\0\u5748\0\u579c\0\u57f0\0\u5844"+ + "\0\u5898\0\u58ec\0\u5940\0\u5994\0\u59e8\0\u5a3c\0\u5a90\0\u5ae4"+ + "\0\u5b38\0\u5b8c\0\u039c\0\u5be0\0\u5c34\0\u5c88\0\u5cdc\0\u5d30"+ + "\0\u5d84\0\u5dd8\0\u039c\0\u5e2c\0\u5e80\0\u5ed4\0\u5f28\0\u039c"+ + "\0\u5f7c\0\u5fd0\0\u6024\0\u6078\0\u60cc\0\u6120\0\u6174\0\u01f8"+ + "\0\u2d48\0\u01f8\0\u61c8\0\u621c\0\u01f8\0\u6270\0\u62c4\0\u6318"+ + "\0\u636c\0\u63c0\0\u6414\0\u6468\0\u64bc\0\u6510\0\u6564\0\u65b8"+ + "\0\u660c\0\u039c\0\u6660\0\u66b4\0\u6708\0\u675c\0\u039c\0\u039c"+ + "\0\u67b0\0\u039c\0\u6804\0\u6858\0\u68ac\0\u6900\0\u6954\0\u039c"+ + "\0\u69a8\0\u69fc\0\u6a50\0\u6aa4\0\u6af8\0\u039c\0\u6b4c\0\u6ba0"+ + "\0\u6bf4\0\u039c\0\u6c48\0\u6c9c\0\u6cf0\0\u6d44\0\u6d98\0\u6dec"+ + "\0\u6e40\0\u6e94\0\u6ee8\0\u6f3c\0\u6f90\0\u6fe4\0\u039c\0\u7038"+ + "\0\u708c\0\u70e0\0\u7134\0\u7188\0\u71dc\0\u039c\0\u7230\0\u7284"+ + "\0\u72d8\0\u732c\0\u7380\0\u73d4\0\u039c\0\u7428\0\u039c\0\u747c"+ + "\0\u74d0\0\u7524\0\u7578\0\u75cc\0\u7620\0\u7674\0\u76c8\0\u771c"+ + "\0\u7770\0\u77c4\0\u7818\0\u786c\0\u78c0\0\u7914\0\u7968\0\u79bc"+ + "\0\u7a10\0\u039c\0\u7a64\0\u039c\0\u7ab8\0\u7b0c\0\u7b60\0\u039c"+ + "\0\u7bb4\0\u7c08\0\u039c\0\u039c\0\u7c5c\0\u7cb0\0\u7d04\0\u7d58"+ + "\0\u7dac\0\u7e00\0\u7e54\0\u039c\0\u7ea8\0\u7efc\0\u7f50\0\u7fa4"+ + "\0\u039c\0\u7ff8\0\u804c\0\u80a0\0\u80f4\0\u039c\0\u8148\0\u819c"+ + "\0\u81f0\0\u8244\0\u8298\0\u039c\0\u82ec\0\u8340\0\u8394\0\u83e8"+ + "\0\u843c\0\u8490\0\u84e4\0\u8538\0\u039c\0\u858c\0\u85e0\0\u039c"+ + "\0\u8634\0\u8688\0\u86dc\0\u039c\0\u039c\0\u8730\0\u8784\0\u87d8"+ + "\0\u6468\0\u882c\0\u8880\0\u88d4\0\u039c\0\u8928\0\u897c\0\u89d0"+ + "\0\u8a24\0\u8a78\0\u039c\0\u8acc\0\u8b20\0\u8b74\0\u8bc8\0\u8c1c"+ + "\0\u8c70\0\u8cc4\0\u8d18\0\u8d6c\0\u8dc0\0\u8e14\0\u8e68\0\u039c"+ + "\0\u8ebc\0\u039c\0\u8f10\0\u039c\0\u8f64\0\u8fb8\0\u900c\0\u9060"+ + "\0\u90b4\0\u9108\0\u915c\0\u039c\0\u039c\0\u91b0\0\u9204\0\u9258"+ + "\0\u92ac\0\u9300\0\u9354\0\u77c4\0\u93a8\0\u93fc\0\u9450\0\u039c"+ + "\0\u94a4\0\u94f8\0\u039c\0\u039c\0\u954c\0\u95a0\0\u95f4\0\u9648"+ + "\0\u969c\0\u96f0\0\u039c\0\u9744\0\u9798\0\u97ec\0\u9840\0\u9894"+ + "\0\u98e8\0\u993c\0\u039c\0\u9990\0\u99e4\0\u9a38\0\u9a8c\0\u9ae0"+ + "\0\u039c\0\u9b34\0\u039c\0\u039c\0\u9b88\0\u9bdc\0\u9c30\0\u039c"+ + "\0\u9c84\0\u9cd8\0\u9d2c\0\u039c\0\u9d80\0\u039c\0\u039c\0\u9dd4"+ + "\0\u9e28\0\u9e7c\0\u9ed0\0\u039c\0\u9f24\0\u9f78\0\u039c\0\u9fcc"+ + "\0\ua020\0\u039c\0\ua074\0\ua0c8\0\u039c\0\u039c\0\ua11c\0\ua170"+ + "\0\ua1c4\0\ua218\0\ua26c\0\u01f8\0\ua2c0\0\ua314\0\ua368\0\u039c"+ + "\0\u039c\0\ua3bc\0\u039c\0\ua410\0\u039c\0\ua464\0\ua4b8\0\ua50c"+ + "\0\ua560\0\ua5b4\0\ua608\0\u039c\0\ua65c\0\ua6b0\0\ua704\0\ua758"+ + "\0\ua7ac\0\ua800\0\ua854\0\ua8a8\0\ua8fc\0\ua950\0\ua9a4\0\ua9f8"+ + "\0\u039c\0\u039c\0\u039c\0\uaa4c\0\uaaa0\0\uaaf4\0\uab48\0\uab9c"+ + "\0\uabf0\0\uac44\0\u039c\0\uac98\0\uacec\0\uad40\0\uad94\0\u039c"+ + "\0\uade8\0\u039c\0\uae3c\0\uae90\0\uaee4\0\uaf38\0\uaf8c\0\uafe0"+ + "\0\ub034\0\u039c\0\ub088\0\ub0dc\0\ub130\0\ub184\0\u039c\0\ub1d8"+ + "\0\ub22c\0\ub280\0\ub2d4\0\u17a0\0\ub328\0\ub37c\0\u039c\0\u039c"+ + "\0\u039c\0\ub3d0\0\u039c"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[707]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); } + return j; + } - /** - * Translates a state to a row index in the transition table - */ - private static final int[] ZZ_ROWMAP = zzUnpackRowMap(); + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); - private static final String ZZ_ROWMAP_PACKED_0 - = "\0\0\0\124\0\250\0\374\0\u0150\0\u01a4\0\u01f8\0\u024c" - + "\0\u01f8\0\u02a0\0\u02f4\0\u0348\0\u039c\0\u03f0\0\u0444\0\u0498" - + "\0\u04ec\0\u0540\0\u01f8\0\u0594\0\u05e8\0\u063c\0\u01f8\0\u01f8" - + "\0\u0690\0\u06e4\0\u0738\0\u078c\0\u07e0\0\u0834\0\u0888\0\u08dc" - + "\0\u0930\0\u0984\0\u09d8\0\u0a2c\0\u0a80\0\u0ad4\0\u0b28\0\u0b7c" - + "\0\u0bd0\0\u0c24\0\u0c78\0\u0ccc\0\u0d20\0\u0d74\0\u01f8\0\u01f8" - + "\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u0dc8\0\u01f8" - + "\0\u01f8\0\u0e1c\0\u0e70\0\u0ec4\0\u0f18\0\u0f6c\0\u01f8\0\u0fc0" - + "\0\u1014\0\u01f8\0\u01f8\0\u1068\0\u10bc\0\u1110\0\u1164\0\u01f8" - + "\0\u11b8\0\u120c\0\u01f8\0\u1260\0\u01f8\0\u12b4\0\u01f8\0\u1308" - + "\0\u135c\0\u13b0\0\u01f8\0\u1404\0\u1458\0\u01f8\0\u01f8\0\u01f8" - + "\0\u14ac\0\u1500\0\u1554\0\u15a8\0\u15fc\0\u01f8\0\u01f8\0\u1650" - + "\0\u01f8\0\u16a4\0\u16f8\0\u174c\0\u17a0\0\u17f4\0\u1848\0\u189c" - + "\0\u01f8\0\u01f8\0\u18f0\0\u1944\0\u1998\0\u19ec\0\u1a40\0\u1a94" - + "\0\u1ae8\0\u039c\0\u1b3c\0\u1b90\0\u1be4\0\u1c38\0\u1c8c\0\u1ce0" - + "\0\u1d34\0\u1d88\0\u1ddc\0\u1e30\0\u1e84\0\u1ed8\0\u1f2c\0\u1f80" - + "\0\u1fd4\0\u2028\0\u207c\0\u20d0\0\u2124\0\u2178\0\u039c\0\u21cc" - + "\0\u2220\0\u2274\0\u22c8\0\u231c\0\u2370\0\u039c\0\u23c4\0\u2418" - + "\0\u246c\0\u24c0\0\u2514\0\u2568\0\u25bc\0\u2610\0\u2664\0\u26b8" - + "\0\u270c\0\u2760\0\u27b4\0\u2808\0\u285c\0\u28b0\0\u2904\0\u2958" - + "\0\u29ac\0\u2a00\0\u2a54\0\u2aa8\0\u2afc\0\u2b50\0\u2ba4\0\u01f8" - + "\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8" - + "\0\u01f8\0\u2bf8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8" - + "\0\u2c4c\0\u01f8\0\u2ca0\0\u120c\0\u2cf4\0\u2d48\0\u2d9c\0\u2df0" - + "\0\u2e44\0\u01f8\0\u01f8\0\u2c4c\0\u2ca0\0\u2e98\0\u01f8\0\u2eec" - + "\0\u2f40\0\u01f8\0\u2f94\0\u2fe8\0\u303c\0\u01f8\0\u3090\0\u01f8" - + "\0\u30e4\0\u01f8\0\u01f8\0\u17a0\0\u3138\0\u318c\0\u31e0\0\u31e0" - + "\0\u3234\0\u3288\0\u32dc\0\u3330\0\u3384\0\u33d8\0\u342c\0\u3480" - + "\0\u039c\0\u34d4\0\u3528\0\u357c\0\u35d0\0\u3624\0\u039c\0\u039c" - + "\0\u3678\0\u36cc\0\u3720\0\u3774\0\u37c8\0\u039c\0\u381c\0\u3870" - + "\0\u38c4\0\u3918\0\u396c\0\u39c0\0\u3a14\0\u039c\0\u3a68\0\u3abc" - + "\0\u3b10\0\u3b64\0\u3bb8\0\u3c0c\0\u3c60\0\u3cb4\0\u3d08\0\u3d5c" - + "\0\u039c\0\u3db0\0\u3e04\0\u3e58\0\u3eac\0\u3f00\0\u3f54\0\u3fa8" - + "\0\u3ffc\0\u039c\0\u4050\0\u40a4\0\u40f8\0\u414c\0\u41a0\0\u41f4" - + "\0\u4248\0\u429c\0\u42f0\0\u4344\0\u4398\0\u43ec\0\u4440\0\u4494" - + "\0\u44e8\0\u453c\0\u039c\0\u4590\0\u45e4\0\u4638\0\u468c\0\u039c" - + "\0\u46e0\0\u4734\0\u01f8\0\u4788\0\u47dc\0\u4830\0\u4884\0\u48d8" - + "\0\u492c\0\u4980\0\u49d4\0\u4a28\0\u4a7c\0\u01f8\0\u4ad0\0\u4b24" - + "\0\u4b78\0\u4bcc\0\u4c20\0\u01f8\0\u4c74\0\u4cc8\0\u4d1c\0\u4d70" - + "\0\u4dc4\0\u4e18\0\u039c\0\u039c\0\u039c\0\u4e6c\0\u039c\0\u4ec0" - + "\0\u039c\0\u4f14\0\u4f68\0\u4fbc\0\u5010\0\u5064\0\u50b8\0\u510c" - + "\0\u5160\0\u51b4\0\u5208\0\u525c\0\u52b0\0\u5304\0\u039c\0\u5358" - + "\0\u039c\0\u53ac\0\u5400\0\u5454\0\u54a8\0\u039c\0\u54fc\0\u5550" - + "\0\u55a4\0\u55f8\0\u564c\0\u56a0\0\u56f4\0\u5748\0\u579c\0\u57f0" - + "\0\u5844\0\u5898\0\u58ec\0\u5940\0\u5994\0\u59e8\0\u5a3c\0\u5a90" - + "\0\u039c\0\u5ae4\0\u5b38\0\u5b8c\0\u5be0\0\u5c34\0\u5c88\0\u5cdc" - + "\0\u039c\0\u5d30\0\u5d84\0\u5dd8\0\u5e2c\0\u039c\0\u5e80\0\u5ed4" - + "\0\u5f28\0\u5f7c\0\u5fd0\0\u6024\0\u6078\0\u01f8\0\u2ca0\0\u01f8" - + "\0\u60cc\0\u6120\0\u01f8\0\u6174\0\u61c8\0\u621c\0\u6270\0\u62c4" - + "\0\u6318\0\u636c\0\u63c0\0\u6414\0\u6468\0\u64bc\0\u6510\0\u039c" - + "\0\u6564\0\u65b8\0\u660c\0\u6660\0\u039c\0\u039c\0\u66b4\0\u039c" - + "\0\u6708\0\u675c\0\u67b0\0\u6804\0\u6858\0\u039c\0\u68ac\0\u6900" - + "\0\u6954\0\u69a8\0\u69fc\0\u039c\0\u6a50\0\u6aa4\0\u6af8\0\u039c" - + "\0\u6b4c\0\u6ba0\0\u6bf4\0\u6c48\0\u6c9c\0\u6cf0\0\u6d44\0\u6d98" - + "\0\u6dec\0\u6e40\0\u6e94\0\u6ee8\0\u039c\0\u6f3c\0\u6f90\0\u6fe4" - + "\0\u7038\0\u708c\0\u70e0\0\u039c\0\u7134\0\u7188\0\u71dc\0\u7230" - + "\0\u7284\0\u72d8\0\u039c\0\u732c\0\u039c\0\u7380\0\u73d4\0\u7428" - + "\0\u747c\0\u74d0\0\u7524\0\u7578\0\u75cc\0\u7620\0\u7674\0\u76c8" - + "\0\u771c\0\u7770\0\u77c4\0\u7818\0\u786c\0\u78c0\0\u7914\0\u039c" - + "\0\u7968\0\u039c\0\u79bc\0\u7a10\0\u7a64\0\u039c\0\u7ab8\0\u7b0c" - + "\0\u039c\0\u039c\0\u7b60\0\u7bb4\0\u7c08\0\u7c5c\0\u7cb0\0\u7d04" - + "\0\u7d58\0\u039c\0\u7dac\0\u7e00\0\u7e54\0\u7ea8\0\u039c\0\u7efc" - + "\0\u7f50\0\u7fa4\0\u7ff8\0\u039c\0\u804c\0\u80a0\0\u80f4\0\u8148" - + "\0\u819c\0\u039c\0\u81f0\0\u8244\0\u8298\0\u82ec\0\u8340\0\u8394" - + "\0\u83e8\0\u843c\0\u039c\0\u8490\0\u84e4\0\u039c\0\u8538\0\u858c" - + "\0\u85e0\0\u039c\0\u039c\0\u8634\0\u8688\0\u86dc\0\u636c\0\u8730" - + "\0\u8784\0\u87d8\0\u039c\0\u882c\0\u8880\0\u88d4\0\u8928\0\u897c" - + "\0\u039c\0\u89d0\0\u8a24\0\u8a78\0\u8acc\0\u8b20\0\u8b74\0\u8bc8" - + "\0\u8c1c\0\u8c70\0\u8cc4\0\u8d18\0\u8d6c\0\u039c\0\u8dc0\0\u039c" - + "\0\u8e14\0\u039c\0\u8e68\0\u8ebc\0\u8f10\0\u8f64\0\u8fb8\0\u900c" - + "\0\u9060\0\u039c\0\u039c\0\u90b4\0\u9108\0\u915c\0\u91b0\0\u9204" - + "\0\u9258\0\u76c8\0\u92ac\0\u9300\0\u9354\0\u039c\0\u93a8\0\u93fc" - + "\0\u039c\0\u039c\0\u9450\0\u94a4\0\u94f8\0\u954c\0\u95a0\0\u95f4" - + "\0\u039c\0\u9648\0\u969c\0\u96f0\0\u9744\0\u9798\0\u97ec\0\u9840" - + "\0\u039c\0\u9894\0\u98e8\0\u993c\0\u9990\0\u99e4\0\u039c\0\u9a38" - + "\0\u039c\0\u039c\0\u9a8c\0\u9ae0\0\u9b34\0\u039c\0\u9b88\0\u9bdc" - + "\0\u9c30\0\u039c\0\u9c84\0\u039c\0\u039c\0\u9cd8\0\u9d2c\0\u9d80" - + "\0\u9dd4\0\u039c\0\u9e28\0\u9e7c\0\u039c\0\u9ed0\0\u9f24\0\u039c" - + "\0\u9f78\0\u9fcc\0\u039c\0\u039c\0\ua020\0\ua074\0\ua0c8\0\ua11c" - + "\0\ua170\0\u01f8\0\ua1c4\0\ua218\0\ua26c\0\u039c\0\u039c\0\ua2c0" - + "\0\u039c\0\ua314\0\u039c\0\ua368\0\ua3bc\0\ua410\0\ua464\0\ua4b8" - + "\0\ua50c\0\u039c\0\ua560\0\ua5b4\0\ua608\0\ua65c\0\ua6b0\0\ua704" - + "\0\ua758\0\ua7ac\0\ua800\0\ua854\0\ua8a8\0\ua8fc\0\u039c\0\u039c" - + "\0\u039c\0\ua950\0\ua9a4\0\ua9f8\0\uaa4c\0\uaaa0\0\uaaf4\0\uab48" - + "\0\u039c\0\uab9c\0\uabf0\0\uac44\0\uac98\0\u039c\0\uacec\0\u039c" - + "\0\uad40\0\uad94\0\uade8\0\uae3c\0\uae90\0\uaee4\0\uaf38\0\u039c" - + "\0\uaf8c\0\uafe0\0\ub034\0\ub088\0\u039c\0\ub0dc\0\ub130\0\ub184" - + "\0\ub1d8\0\u174c\0\ub22c\0\ub280\0\u039c\0\u039c\0\u039c\0\ub2d4" - + "\0\u039c"; + private static final String ZZ_TRANS_PACKED_0 = + "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\7"+ + "\1\16\1\17\1\20\1\21\1\12\1\22\1\23\1\24"+ + "\1\25\2\15\2\25\1\15\1\26\1\7\1\27\1\30"+ + "\1\31\1\32\1\33\1\34\1\15\1\35\1\36\1\37"+ + "\1\40\1\41\1\42\1\43\1\44\1\45\1\46\1\47"+ + "\1\15\1\50\1\15\1\51\1\52\1\15\1\53\2\15"+ + "\1\54\12\15\1\55\1\56\1\57\1\60\1\61\1\62"+ + "\1\63\1\64\1\65\1\66\1\67\1\70\1\71\1\72"+ + "\1\73\1\74\1\75\1\76\1\77\1\7\1\12\1\7"+ + "\1\100\1\101\1\102\13\100\1\103\10\100\1\104\74\100"+ + "\1\105\1\101\1\102\24\105\1\106\1\103\73\105\1\7"+ + "\1\107\1\110\1\111\2\7\1\112\4\7\1\113\1\114"+ + "\4\7\2\112\2\7\1\112\4\7\46\112\22\7\1\111"+ + "\1\7\1\115\1\116\1\117\7\115\1\120\111\115\1\121"+ + "\1\101\1\102\24\121\1\122\1\121\1\123\72\121\126\0"+ + "\1\11\124\0\1\12\10\0\1\12\105\0\1\12\5\0"+ + "\1\124\1\125\7\0\1\126\123\0\1\127\114\0\2\15"+ + "\7\0\7\15\4\0\46\15\23\0\1\15\10\0\1\130"+ + "\124\0\1\131\1\132\4\0\2\133\2\0\2\133\105\0"+ + "\1\134\3\0\1\135\1\136\1\0\1\137\3\0\2\134"+ + "\2\0\1\134\4\0\46\134\37\0\1\140\1\0\1\141"+ + "\123\0\1\142\117\0\1\133\5\0\1\143\1\144\1\145"+ + "\1\0\1\146\1\147\1\150\6\0\1\150\22\0\1\145"+ + "\55\0\1\133\5\0\2\25\2\0\2\25\1\150\6\0"+ + "\1\150\104\0\1\151\10\0\1\152\126\0\1\153\100\0"+ + "\2\15\7\0\7\15\4\0\1\15\1\154\44\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\155"+ + "\1\156\42\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\3\15\1\157\12\15\1\160\5\15\1\161\1\162"+ + "\20\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\163\1\15\1\164\35\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\165\3\15\1\166"+ + "\6\15\1\167\1\15\1\170\25\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\171\6\15\1\172"+ + "\1\15\1\173\3\15\1\174\26\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\15\1\175\22\15\1\176"+ + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\177\1\200\7\15\1\201\32\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\1\15\1\202\1\203"+ + "\1\204\3\15\1\205\10\15\1\206\1\15\1\207\23\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\6\15"+ + "\1\210\1\15\1\211\4\15\1\212\5\15\1\213\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\6\15"+ + "\1\214\1\15\1\215\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\216\4\15\1\217\3\15"+ + "\1\220\6\15\1\221\23\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\222\2\15\1\223\1\224"+ + "\2\15\1\225\1\226\32\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\227\4\15\1\230\36\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\231\5\15\1\232\25\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\233\1\15\1\234\7\15"+ + "\1\235\2\15\1\236\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\237\45\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\240\3\15\1\241"+ + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\242\4\15\1\243\36\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\244\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\245"+ + "\7\15\1\246\32\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\10\15\1\247\35\15\23\0\1\15\15\0"+ + "\1\250\123\0\1\251\75\0\1\252\25\0\1\253\76\0"+ + "\1\254\24\0\1\255\77\0\1\256\23\0\1\257\123\0"+ + "\1\260\106\0\1\100\2\0\13\100\1\0\10\100\1\0"+ + "\74\100\2\0\1\102\121\0\1\261\2\0\13\261\1\262"+ + "\1\263\3\261\2\263\2\261\1\264\1\265\1\261\1\266"+ + "\1\267\6\261\1\270\1\271\1\261\1\272\1\261\1\273"+ + "\7\261\1\274\41\261\3\0\1\105\2\0\24\105\2\0"+ + "\73\105\1\261\2\0\13\261\1\262\10\261\1\264\1\265"+ + "\1\261\1\266\1\267\6\261\1\270\1\271\1\261\1\272"+ + "\1\261\1\273\7\261\1\274\41\261\5\0\1\110\124\0"+ + "\1\111\10\0\1\111\105\0\1\111\7\0\2\275\1\276"+ + "\3\0\1\277\1\300\1\0\7\275\4\0\46\275\23\0"+ + "\1\275\3\0\1\111\2\0\1\275\5\0\1\114\4\0"+ + "\2\275\2\0\1\275\4\0\46\275\22\0\1\111\3\0"+ + "\1\117\125\0\1\301\1\0\1\302\12\0\2\302\2\0"+ + "\1\302\4\0\46\302\24\0\1\121\2\0\24\121\1\0"+ + "\1\121\1\0\72\121\1\303\2\0\24\303\1\264\1\303"+ + "\1\304\1\266\1\267\6\303\1\270\1\271\1\303\1\305"+ + "\1\303\1\273\7\303\1\306\41\303\3\0\1\124\1\307"+ + "\1\310\121\124\5\311\1\312\116\311\11\0\1\313\120\0"+ + "\1\314\12\0\2\314\2\0\1\314\4\0\46\314\43\0"+ + "\2\133\2\0\2\133\1\150\6\0\1\150\75\0\1\315"+ + "\1\134\1\316\2\0\1\317\1\320\2\0\2\134\2\315"+ + "\2\134\1\315\4\0\46\315\23\0\1\134\15\0\1\321"+ + "\121\0\1\322\1\0\1\323\123\0\1\324\117\0\1\133"+ + "\5\0\1\143\1\144\2\0\1\146\1\147\1\150\6\0"+ + "\1\150\100\0\1\133\5\0\2\144\2\0\2\144\1\150"+ + "\6\0\1\150\106\0\1\325\1\326\1\0\4\326\4\0"+ + "\1\326\1\0\2\326\1\0\1\326\6\0\2\326\12\0"+ + "\1\326\1\0\1\326\5\0\2\326\41\0\1\133\5\0"+ + "\1\147\1\144\2\0\2\147\1\150\6\0\1\150\100\0"+ + "\1\133\5\0\1\327\1\144\2\0\2\327\1\150\6\0"+ + "\1\150\106\0\2\330\2\0\2\330\1\0\1\331\66\0"+ + "\1\331\14\0\1\332\12\0\2\332\2\0\1\332\4\0"+ + "\46\332\32\0\2\15\7\0\7\15\4\0\2\15\1\333"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\334\11\15\1\335\22\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\10\15\1\336\35\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\5\15\1\337"+ + "\40\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\340\37\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\341\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\342\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\343"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\344\2\15\1\345\4\15\1\346\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\347"+ + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\350\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\15\1\351\44\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\352\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\353"+ + "\3\15\1\354\36\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\355\20\15\1\356\24\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\357\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\360\31\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\361\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\17\15\1\362\5\15\1\363\20\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15"+ + "\1\364\22\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\365\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\366\7\15\1\367\6\15"+ + "\1\370\23\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\371\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\372\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\26\15\1\373\17\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15"+ + "\1\374\10\15\1\375\33\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\21\15\1\376\24\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\6\15\1\377\2\15"+ + "\1\u0100\34\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\32\15\1\u0101\13\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\21\15\1\u0102\24\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0103\43\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\u0104\1\15\1\u0105\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\15\15\1\u0106\1\u0107\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\21\15\1\u0108"+ + "\24\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\10\15\1\u0109\35\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u010a\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\5\15\1\u010b\40\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u010c"+ + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\10\15\1\u010d\35\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\10\15\1\u010e\35\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\10\15\1\u010f\35\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0110"+ + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u0111\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u0112\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u0113\4\15\1\u0114"+ + "\2\15\1\u0115\33\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\5\15\1\u0116\40\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\u0117\45\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\3\15\1\u0118\42\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\5\15"+ + "\1\u0119\1\u011a\1\u011b\6\15\1\u011c\27\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\1\15\1\u011d\44\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\u011e\33\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\11\15\1\u011f\34\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\11\15\1\u0120\34\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\1\15\1\u0121\44\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\44\15"+ + "\1\u0122\1\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\23\15\1\u0123\22\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\15\15\1\u0124\30\15\23\0\1\15"+ + "\15\0\1\u0125\125\0\1\u0126\3\0\2\u0126\116\0\2\u0127"+ + "\1\0\4\u0127\4\0\1\u0127\1\0\2\u0127\1\0\1\u0127"+ + "\6\0\2\u0127\12\0\1\u0127\1\0\1\u0127\5\0\2\u0127"+ + "\47\0\2\u0128\1\0\4\u0128\4\0\1\u0128\1\0\2\u0128"+ + "\1\0\1\u0128\6\0\2\u0128\12\0\1\u0128\1\0\1\u0128"+ + "\5\0\2\u0128\36\0\1\u0129\12\0\2\u0129\2\0\1\u0129"+ + "\4\0\46\u0129\40\0\1\277\1\300\122\0\1\300\1\0"+ + "\1\u012a\113\0\1\u012b\12\0\2\u012b\2\0\1\u012b\4\0"+ + "\46\u012b\32\0\1\u012c\1\302\1\u012d\2\0\1\115\1\u012e"+ + "\2\0\2\302\2\u012c\2\302\1\u012c\4\0\46\u012c\23\0"+ + "\1\302\2\0\1\310\121\0\5\311\1\u012f\116\311\4\0"+ + "\1\310\1\312\124\0\2\314\3\0\1\u0130\3\0\7\314"+ + "\4\0\46\314\23\0\1\314\6\0\2\315\1\u0131\2\0"+ + "\1\317\1\u0132\1\u0133\1\0\7\315\4\0\46\315\23\0"+ + "\1\315\6\0\1\u0134\12\0\2\u0134\2\0\1\u0134\4\0"+ + "\46\u0134\32\0\1\u0135\5\0\1\320\4\0\2\u0135\2\0"+ + "\1\u0135\4\0\46\u0135\41\0\1\u0136\125\0\2\u0137\1\0"+ + "\4\u0137\4\0\1\u0137\1\0\2\u0137\1\0\1\u0137\6\0"+ + "\2\u0137\12\0\1\u0137\1\0\1\u0137\5\0\2\u0137\41\0"+ + "\1\133\5\0\1\u0138\1\144\2\0\2\u0138\1\150\6\0"+ + "\1\150\106\0\2\330\2\0\2\330\105\0\2\332\7\0"+ + "\7\332\4\0\46\332\23\0\1\332\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\u0139\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\13\15\1\u013a\32\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u013b"+ + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\14\15\1\u013c\31\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\20\15\1\u013d\25\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u013e\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u013f"+ + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u0140\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0141\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\5\15\1\u0142\40\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u0143"+ + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\u0144\2\15\1\u0145\34\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u0146\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u0147"+ + "\7\15\1\u0148\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\21\15\1\u0149\24\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u014a\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u014b"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u014c\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\15\1\u014d\44\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\16\15\1\u014e\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u014f"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u0150\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u0151\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\5\15\1\u0152\40\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u0153"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\16\15\1\u0154\27\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\26\15\1\u0155\17\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\26\15\1\u0156\17\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u0157"+ + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\u0158\37\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0159\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u015a\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u015b"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\1\15\1\u015c\44\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\7\15\1\u015d\6\15\1\u015e\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u015f"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\7\15\1\u0160\36\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\u0161\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u0162\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u0163"+ + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\u0164\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\6\15\1\u0165\37\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\7\15\1\u0166\36\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0167"+ + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\5\15\1\u0168\40\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\26\15\1\u0169\17\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\14\15\1\u016a\31\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\20\15\1\u016b"+ + "\25\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\16\15\1\u016c\27\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\24\15\1\u016d\21\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u016e\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u016f"+ + "\13\15\1\u0170\21\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\4\15\1\u0171\41\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\16\15\1\u0172\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\22\15\1\u0173"+ + "\23\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\20\15\1\u0174\25\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\13\15\1\u0175\32\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\15\1\u0176\44\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u0177"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\14\15\1\u0178\31\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\27\15\1\u0179\3\15\1\u017a\6\15\1\u017b"+ + "\3\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\7\15\1\u017c\36\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u017d\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\u017e\45\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u017f\33\15"+ + "\23\0\1\15\17\0\1\u0180\3\0\2\u0180\116\0\2\u0181"+ + "\1\0\4\u0181\4\0\1\u0181\1\0\2\u0181\1\0\1\u0181"+ + "\6\0\2\u0181\12\0\1\u0181\1\0\1\u0181\5\0\2\u0181"+ + "\47\0\2\u0182\1\0\4\u0182\4\0\1\u0182\1\0\2\u0182"+ + "\1\0\1\u0182\6\0\2\u0182\12\0\1\u0182\1\0\1\u0182"+ + "\5\0\2\u0182\36\0\2\u0129\4\0\1\277\1\300\1\0"+ + "\7\u0129\4\0\46\u0129\23\0\1\u0129\1\u012a\2\0\13\u012a"+ + "\1\u0183\105\u012a\6\0\2\u012b\1\u0184\2\0\1\u0185\3\0"+ + "\7\u012b\4\0\46\u012b\23\0\1\u012b\6\0\2\u012c\1\u0186"+ + "\2\0\1\115\1\u0187\1\u0188\1\0\7\u012c\4\0\46\u012c"+ + "\23\0\1\u012c\6\0\1\u0189\12\0\2\u0189\2\0\1\u0189"+ + "\4\0\46\u0189\32\0\1\u018a\5\0\1\u012e\4\0\2\u018a"+ + "\2\0\1\u018a\4\0\46\u018a\24\0\4\311\1\310\1\u012f"+ + "\116\311\6\0\1\u018b\12\0\2\u018b\2\0\1\u018b\4\0"+ + "\46\u018b\32\0\1\u0135\5\0\1\u0132\1\u0133\3\0\2\u0135"+ + "\2\0\1\u0135\4\0\46\u0135\40\0\1\u0133\1\0\1\u018c"+ + "\113\0\1\u018d\1\u0134\3\0\1\317\1\320\2\0\2\u0134"+ + "\2\u018d\2\u0134\1\u018d\4\0\46\u018d\23\0\1\u0134\6\0"+ + "\2\u0135\1\u018e\3\0\1\u018f\1\u0133\1\0\7\u0135\4\0"+ + "\46\u0135\23\0\1\u0135\17\0\2\u0190\1\0\4\u0190\4\0"+ + "\1\u0190\1\0\2\u0190\1\0\1\u0190\6\0\2\u0190\12\0"+ + "\1\u0190\1\0\1\u0190\5\0\2\u0190\41\0\1\133\5\0"+ + "\1\u0191\1\144\2\0\2\u0191\1\150\6\0\1\150\75\0"+ + "\2\15\7\0\7\15\4\0\4\15\1\u0192\41\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u0193"+ + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\24\15\1\u0194\21\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\7\15\1\u0195\36\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\10\15\1\u0196\35\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\20\15\1\u0197"+ + "\25\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u0198\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u0199\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u019a\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u019b"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\12\15\1\u019c\33\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\30\15\1\u019d\10\15\1\u019e\4\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u019f"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\1\15\1\u01a0\44\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\5\15\1\u01a1\40\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\15\1\u01a2\44\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\12\15\1\u01a3"+ + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\32\15\1\u01a4\13\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\6\15\1\u01a5\37\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u01a6\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\33\15\1\u01a7"+ + "\12\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u01a8\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u01a9\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\17\15\1\u01aa\26\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u01ab"+ + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\u01ac\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\15\1\u01ad\44\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u01ae\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u01af"+ + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u01b0\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\15\15\1\u01b1\30\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u01b2\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u01b3"+ + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u01b4\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u01b5\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\23\15\1\u01b6\22\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u01b7"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\23\15\1\u01b8\22\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u01b9\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u01ba\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u01bb"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\37\15\1\u01bc\2\15\1\u01bd\3\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u01be\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\32\15\1\u01bf"+ + "\13\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u01c0\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\11\15\1\u01c1\34\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u01c2\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u01c3"+ + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\12\15\1\u01c4\33\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\15\1\u01c5\44\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\u01c6\45\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u01c7\31\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15"+ + "\1\u01c8\35\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\1\15\1\u01c9\44\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u01ca\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u01cb\43\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\30\15"+ + "\1\u01cc\15\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01cd\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u01ce\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u01cf\35\15"+ + "\23\0\1\15\1\u012a\2\0\11\u012a\1\u0183\1\u012a\1\u0183"+ + "\105\u012a\6\0\1\u01d0\12\0\2\u01d0\2\0\1\u01d0\4\0"+ + "\46\u01d0\32\0\1\u01d1\12\0\2\u01d1\2\0\1\u01d1\4\0"+ + "\46\u01d1\32\0\1\u018a\5\0\1\u0187\1\u0188\3\0\2\u018a"+ + "\2\0\1\u018a\4\0\46\u018a\40\0\1\u0188\1\0\1\u01d2"+ + "\113\0\1\u01d3\1\u0189\3\0\1\115\1\u012e\2\0\2\u0189"+ + "\2\u01d3\2\u0189\1\u01d3\4\0\46\u01d3\23\0\1\u0189\6\0"+ + "\2\u018a\1\u01d4\3\0\1\u01d5\1\u0188\1\0\7\u018a\4\0"+ + "\46\u018a\23\0\1\u018a\6\0\1\u018d\1\u018b\3\0\1\317"+ + "\1\u0132\1\u0133\1\0\2\u018b\2\u018d\2\u018b\1\u018d\4\0"+ + "\46\u018d\23\0\1\u018b\1\u018c\2\0\13\u018c\1\u01d6\105\u018c"+ + "\6\0\2\u018d\1\u018e\2\0\1\317\1\u0132\1\u0133\1\0"+ + "\7\u018d\4\0\46\u018d\23\0\1\u018d\6\0\1\u01d7\12\0"+ + "\2\u01d7\2\0\1\u01d7\4\0\46\u01d7\40\0\1\u018f\1\u0133"+ + "\125\0\2\u01d8\1\0\4\u01d8\4\0\1\u01d8\1\0\2\u01d8"+ + "\1\0\1\u01d8\6\0\2\u01d8\12\0\1\u01d8\1\0\1\u01d8"+ + "\5\0\2\u01d8\41\0\1\133\5\0\1\u01d9\1\144\2\0"+ + "\2\u01d9\1\150\6\0\1\150\75\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01da\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u01db\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u01dc\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\u01dd\31\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01de\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\41\15\1\u01df\4\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u01e0\40\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15"+ + "\1\u01e1\27\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\1\15\1\u01e2\44\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\u01e3\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\20\15\1\u01e4\25\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\u01e5\33\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01e6\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\u01e7\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\21\15\1\u01e8\24\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\3\15"+ + "\1\u01e9\42\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\11\15\1\u01ea\34\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u01eb\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\15\15\1\u01ec\30\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15"+ + "\1\u01ed\35\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01ee\4\15\1\u01ef\30\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u01f0\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15"+ + "\1\u01f1\34\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\23\15\1\u01f2\22\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u01f3\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u01f4\31\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15"+ + "\1\u01f5\27\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u01f6\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\5\15\1\u01f7\40\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u01f8\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15"+ + "\1\u01f9\22\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\u01fa\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u01fb\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\20\15\1\u01fc\25\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\7\15"+ + "\1\u01fd\36\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\3\15\1\u01fe\42\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\u01ff\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u0200\40\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\30\15"+ + "\1\u0201\13\15\1\u0202\1\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\11\15\1\u0203\34\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\26\15\1\u0204\17\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\5\15"+ + "\1\u0205\40\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\6\15\1\u0206\37\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\26\15\1\u0207\17\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\16\15\1\u0208\27\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15"+ + "\1\u0209\22\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\1\15\1\u020a\44\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\10\15\1\u020b\35\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\26\15\1\u020c\17\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15"+ + "\1\u020d\44\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\12\15\1\u020e\33\15\23\0\1\15\6\0\2\u01d0"+ + "\3\0\1\u0185\3\0\7\u01d0\4\0\46\u01d0\23\0\1\u01d0"+ + "\6\0\1\u01d3\1\u01d1\3\0\1\115\1\u0187\1\u0188\1\0"+ + "\2\u01d1\2\u01d3\2\u01d1\1\u01d3\4\0\46\u01d3\23\0\1\u01d1"+ + "\1\u01d2\2\0\13\u01d2\1\u020f\105\u01d2\6\0\2\u01d3\1\u01d4"+ + "\2\0\1\115\1\u0187\1\u0188\1\0\7\u01d3\4\0\46\u01d3"+ + "\23\0\1\u01d3\6\0\1\u0210\12\0\2\u0210\2\0\1\u0210"+ + "\4\0\46\u0210\40\0\1\u01d5\1\u0188\106\0\1\u018c\2\0"+ + "\10\u018c\1\u0211\1\u01d6\1\u018c\1\u01d6\105\u018c\6\0\2\u01d7"+ + "\4\0\1\u018f\1\u0133\1\0\7\u01d7\4\0\46\u01d7\23\0"+ + "\1\u01d7\17\0\2\u0212\1\0\4\u0212\4\0\1\u0212\1\0"+ + "\2\u0212\1\0\1\u0212\6\0\2\u0212\12\0\1\u0212\1\0"+ + "\1\u0212\5\0\2\u0212\41\0\1\133\5\0\1\u0213\1\144"+ + "\2\0\2\u0213\1\150\6\0\1\150\75\0\2\15\7\0"+ + "\7\15\4\0\37\15\1\u0214\6\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u0215\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u0216"+ + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\1\15\1\u0217\44\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u0218\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u0219\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u021a"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u021b\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\u021c\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u021d\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u021e"+ + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\43\15\1\u021f\2\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\34\15\1\u0220\11\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\5\15\1\u0221\40\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0222"+ + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\u0223\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0224\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u0225\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u0226"+ + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\37\15\1\u0227\6\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\11\15\1\u0228\34\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u0229\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\5\15\1\u022a"+ + "\40\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\u022b\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\22\15\1\u022c\23\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\7\15\1\u022d\36\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\24\15\1\u022e"+ + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\1\15\1\u022f\44\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\u0230\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u0231\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\u0232"+ + "\37\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\13\15\1\u0233\32\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0234\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u0235\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u0236"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u0237\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0238\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u0239\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u023a"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u023b\34\15\23\0\1\15\1\u01d2\2\0\10\u01d2"+ + "\1\u023c\1\u020f\1\u01d2\1\u020f\105\u01d2\6\0\2\u0210\4\0"+ + "\1\u01d5\1\u0188\1\0\7\u0210\4\0\46\u0210\23\0\1\u0210"+ + "\17\0\2\u023d\1\0\4\u023d\4\0\1\u023d\1\0\2\u023d"+ + "\1\0\1\u023d\6\0\2\u023d\12\0\1\u023d\1\0\1\u023d"+ + "\5\0\2\u023d\41\0\1\133\5\0\1\u023e\1\144\2\0"+ + "\2\u023e\1\150\6\0\1\150\75\0\2\15\7\0\7\15"+ + "\4\0\7\15\1\u023f\36\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u0240\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\3\15\1\u0241\42\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\31\15"+ + "\1\u0242\14\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\26\15\1\u0243\17\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u0244\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u0245\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\5\15"+ + "\1\u0246\40\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\26\15\1\u0247\17\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\u0248\42\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u0249\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15"+ + "\1\u024a\43\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\u024b\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\5\15\1\u024c\40\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\36\15\1\u024d\7\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15"+ + "\1\u024e\35\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u024f\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\7\15\1\u0250\36\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u0251\34\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15"+ + "\1\u0252\35\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u0253\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u0254\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u0255\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15"+ + "\1\u0256\22\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u0257\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\3\15\1\u0258\3\15\4\0\46\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u0259\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15"+ + "\1\u025a\44\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\20\15\1\u025b\25\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\u025c\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u025d\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\31\15"+ + "\1\u025e\11\15\1\u025f\2\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\22\15\1\u0260\23\15\23\0\1\15"+ + "\17\0\2\u0261\1\0\4\u0261\4\0\1\u0261\1\0\2\u0261"+ + "\1\0\1\u0261\6\0\2\u0261\12\0\1\u0261\1\0\1\u0261"+ + "\5\0\2\u0261\41\0\1\133\5\0\1\u0262\1\144\2\0"+ + "\2\u0262\1\150\6\0\1\150\75\0\2\15\7\0\7\15"+ + "\4\0\24\15\1\u0263\21\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\26\15\1\u0264\17\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\7\15\1\u0265\36\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15"+ + "\1\u0266\43\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u0267\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u0268\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u0269\34\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\26\15"+ + "\1\u026a\17\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\7\15\1\u026b\36\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u026c\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\7\15\1\u026d\36\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15"+ + "\1\u026e\34\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\14\15\1\u026f\31\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\24\15\1\u0270\21\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0271\43\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\u0272\31\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u0273\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\u0274\42\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0275\43\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\u0276\31\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\12\15\1\u0277\33\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u0278\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\7\15\1\u0279\36\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15"+ + "\1\u027a\34\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\u027b\27\15\23\0\1\15\17\0\2\u027c"+ + "\1\0\4\u027c\4\0\1\u027c\1\0\2\u027c\1\0\1\u027c"+ + "\6\0\2\u027c\12\0\1\u027c\1\0\1\u027c\5\0\2\u027c"+ + "\41\0\1\133\5\0\1\u027d\1\144\2\0\2\u027d\1\150"+ + "\6\0\1\150\75\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\u027e\33\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\13\15\1\u027f\32\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\11\15\1\u0280\34\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\20\15\1\u0281\25\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\20\15"+ + "\1\u0282\25\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\15\15\1\u0283\30\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\u0284\42\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\6\15\1\u0285\37\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\u0286\33\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\37\15\1\u0287\6\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\44\15\1\u0288\1\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\1\u0289\45\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u028a"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\10\15\1\u028b\35\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\10\15\1\u028c\35\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\7\15\1\u028d\36\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u028e"+ + "\42\15\23\0\1\15\11\0\1\133\5\0\1\u028f\1\144"+ + "\2\0\2\u028f\1\150\6\0\1\150\75\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0290\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\10\15\1\u0291\35\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\35\15\1\u0292"+ + "\10\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\14\15\1\u0293\31\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0294\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\7\15\1\u0295\36\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u0296"+ + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\16\15\1\u0297\27\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\23\15\1\u0298\22\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\26\15\1\u0299\17\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\21\15\1\u029a"+ + "\24\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\22\15\1\u029b\23\15\23\0\1\15\11\0\1\133\5\0"+ + "\1\u029c\1\144\2\0\2\u029c\1\150\6\0\1\150\75\0"+ + "\2\15\7\0\7\15\4\0\40\15\1\u029d\5\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u029e"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\13\15\1\u029f\32\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u02a0\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\44\15\1\u02a1\1\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\24\15\1\u02a2"+ + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\23\15\1\u02a3\22\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u02a4\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u02a5\42\15\23\0"+ + "\1\15\11\0\1\133\5\0\1\u02a6\1\144\2\0\2\u02a6"+ + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0"+ + "\16\15\1\u02a7\27\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\6\15\1\u02a8\37\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u02a9\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u02aa"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\13\15\1\u02ab\32\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u02ac\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u02ad\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\21\15\1\u02ae"+ + "\24\15\23\0\1\15\11\0\1\133\5\0\1\u02af\1\144"+ + "\2\0\2\u02af\1\150\6\0\1\150\75\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u02b0\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\16\15\1\u02b1\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\23\15\1\u02b2"+ + "\22\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u02b3\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\44\15\1\u02b4\1\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\44\15\1\u02b5\1\15\23\0"+ + "\1\15\11\0\1\133\5\0\1\u02b6\1\144\2\0\2\u02b6"+ + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0"+ + "\21\15\1\u02b7\24\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u02b8\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\40\15\1\u02b9\5\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u02ba"+ + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\13\15\1\u02bb\32\15\23\0\1\15\11\0\1\133\5\0"+ + "\1\u02bc\1\144\2\0\2\u02bc\1\150\6\0\1\150\75\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u02bd\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u02be"+ + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\23\15\1\u02bf\22\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\23\15\1\u02c0\22\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\22\15\1\u02c1\23\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\12\15\1\u02c2"+ + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\21\15\1\u02c3\24\15\23\0\1\15"; - private static int[] zzUnpackRowMap() { - int[] result = new int[705]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; + private static int [] zzUnpackTrans() { + int [] result = new int[46116]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); } + return j; + } - private static int zzUnpackRowMap(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); - } - return j; + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\6\0\1\11\1\1\1\11\11\1\1\11\3\1\1\11"+ + "\27\1\10\11\1\1\2\11\5\1\1\11\2\1\2\11"+ + "\4\1\1\11\2\1\1\11\1\1\1\11\1\1\1\11"+ + "\3\1\1\11\1\1\1\0\3\11\2\0\1\1\1\0"+ + "\1\1\2\11\1\1\1\11\3\1\1\0\2\1\1\0"+ + "\2\11\1\0\75\1\12\11\1\1\6\11\1\1\1\11"+ + "\1\1\6\0\2\11\3\1\1\11\2\0\1\11\3\0"+ + "\1\11\1\0\1\11\1\1\2\11\4\1\1\0\113\1"+ + "\1\11\12\0\1\11\5\0\1\11\111\1\1\11\1\0"+ + "\1\11\1\1\1\0\1\11\12\0\100\1\10\0\67\1"+ + "\2\0\153\1\1\11\107\1"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[707]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); } + return j; + } - /** - * The transition table of the DFA - */ - private static final int[] ZZ_TRANS = zzUnpackTrans(); + /** the input device */ + private java.io.Reader zzReader; - private static final String ZZ_TRANS_PACKED_0 - = "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\7" - + "\1\16\1\17\1\20\1\21\1\12\1\22\1\23\1\24" - + "\1\25\2\15\2\25\1\15\1\26\1\7\1\27\1\30" - + "\1\31\1\32\1\33\1\34\1\15\1\35\1\36\1\37" - + "\1\40\1\41\1\42\1\43\1\44\1\45\1\46\1\47" - + "\1\15\1\50\1\15\1\51\1\52\1\15\1\53\2\15" - + "\1\54\12\15\1\55\1\56\1\57\1\60\1\61\1\62" - + "\1\63\1\64\1\65\1\66\1\67\1\70\1\71\1\72" - + "\1\73\1\74\1\75\1\76\1\77\1\7\1\12\1\7" - + "\1\100\1\101\1\102\13\100\1\103\10\100\1\104\74\100" - + "\1\105\1\101\1\102\24\105\1\106\1\103\73\105\1\7" - + "\1\107\1\110\1\111\2\7\1\112\4\7\1\113\1\114" - + "\4\7\2\112\2\7\1\112\4\7\46\112\22\7\1\111" - + "\1\7\1\115\1\116\1\117\7\115\1\120\111\115\1\121" - + "\1\101\1\102\24\121\1\122\1\121\1\123\72\121\126\0" - + "\1\11\124\0\1\12\10\0\1\12\105\0\1\12\5\0" - + "\1\124\1\125\7\0\1\126\123\0\1\127\114\0\2\15" - + "\7\0\7\15\4\0\46\15\23\0\1\15\10\0\1\130" - + "\124\0\1\131\1\132\4\0\2\133\2\0\2\133\105\0" - + "\1\134\3\0\1\135\1\136\1\0\1\137\3\0\2\134" - + "\2\0\1\134\4\0\46\134\37\0\1\140\1\0\1\141" - + "\123\0\1\142\117\0\1\133\5\0\1\143\1\144\1\145" - + "\1\0\1\146\1\147\1\150\6\0\1\150\22\0\1\145" - + "\55\0\1\133\5\0\2\25\2\0\2\25\1\150\6\0" - + "\1\150\104\0\1\151\10\0\1\152\103\0\2\15\7\0" - + "\7\15\4\0\1\15\1\153\44\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\154\1\155\42\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\3\15" - + "\1\156\12\15\1\157\5\15\1\160\1\161\20\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\162" - + "\1\15\1\163\35\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\164\3\15\1\165\6\15\1\166" - + "\1\15\1\167\25\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\170\6\15\1\171\1\15\1\172" - + "\3\15\1\173\26\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\15\1\174\22\15\1\175\21\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\176" - + "\1\177\7\15\1\200\32\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\1\15\1\201\1\202\1\203\3\15" - + "\1\204\10\15\1\205\1\15\1\206\23\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\6\15\1\207\1\15" - + "\1\210\4\15\1\211\5\15\1\212\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\6\15\1\213\1\15" - + "\1\214\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\215\4\15\1\216\3\15\1\217\6\15" - + "\1\220\23\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\221\2\15\1\222\1\223\2\15\1\224" - + "\1\225\32\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\226\4\15\1\227\36\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\12\15\1\230\5\15" - + "\1\231\25\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\232\1\15\1\233\7\15\1\234\2\15" - + "\1\235\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\236\45\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\237\3\15\1\240\36\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\241" - + "\4\15\1\242\36\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\243\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\244\7\15\1\245" - + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\10\15\1\246\35\15\23\0\1\15\15\0\1\247\123\0" - + "\1\250\75\0\1\251\25\0\1\252\76\0\1\253\24\0" - + "\1\254\77\0\1\255\23\0\1\256\123\0\1\257\106\0" - + "\1\100\2\0\13\100\1\0\10\100\1\0\74\100\2\0" - + "\1\102\121\0\1\260\2\0\13\260\1\261\1\262\3\260" - + "\2\262\2\260\1\263\1\264\1\260\1\265\1\266\6\260" - + "\1\267\1\270\1\260\1\271\1\260\1\272\7\260\1\273" - + "\41\260\3\0\1\105\2\0\24\105\2\0\73\105\1\260" - + "\2\0\13\260\1\261\10\260\1\263\1\264\1\260\1\265" - + "\1\266\6\260\1\267\1\270\1\260\1\271\1\260\1\272" - + "\7\260\1\273\41\260\5\0\1\110\124\0\1\111\10\0" - + "\1\111\105\0\1\111\7\0\2\274\1\275\3\0\1\276" - + "\1\277\1\0\7\274\4\0\46\274\23\0\1\274\3\0" - + "\1\111\2\0\1\274\5\0\1\114\4\0\2\274\2\0" - + "\1\274\4\0\46\274\22\0\1\111\3\0\1\117\125\0" - + "\1\300\1\0\1\301\12\0\2\301\2\0\1\301\4\0" - + "\46\301\24\0\1\121\2\0\24\121\1\0\1\121\1\0" - + "\72\121\1\302\2\0\24\302\1\263\1\302\1\303\1\265" - + "\1\266\6\302\1\267\1\270\1\302\1\304\1\302\1\272" - + "\7\302\1\305\41\302\3\0\1\124\1\306\1\307\121\124" - + "\5\310\1\311\116\310\11\0\1\312\120\0\1\313\12\0" - + "\2\313\2\0\1\313\4\0\46\313\43\0\2\133\2\0" - + "\2\133\1\150\6\0\1\150\75\0\1\314\1\134\1\315" - + "\2\0\1\316\1\317\2\0\2\134\2\314\2\134\1\314" - + "\4\0\46\314\23\0\1\134\15\0\1\320\121\0\1\321" - + "\1\0\1\322\123\0\1\323\117\0\1\133\5\0\1\143" - + "\1\144\2\0\1\146\1\147\1\150\6\0\1\150\100\0" - + "\1\133\5\0\2\144\2\0\2\144\1\150\6\0\1\150" - + "\106\0\1\324\1\325\1\0\4\325\4\0\1\325\1\0" - + "\2\325\1\0\1\325\6\0\2\325\12\0\1\325\1\0" - + "\1\325\5\0\2\325\41\0\1\133\5\0\1\147\1\144" - + "\2\0\2\147\1\150\6\0\1\150\100\0\1\133\5\0" - + "\1\326\1\144\2\0\2\326\1\150\6\0\1\150\106\0" - + "\2\327\2\0\2\327\1\0\1\330\66\0\1\330\14\0" - + "\2\15\7\0\7\15\4\0\2\15\1\331\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\332" - + "\11\15\1\333\22\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\10\15\1\334\35\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\5\15\1\335\40\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\336" - + "\37\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\3\15\1\337\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\340\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\341\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\342" - + "\2\15\1\343\4\15\1\344\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\10\15\1\345\35\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\346" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\15\1\347\44\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\350\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\351\3\15\1\352" - + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\353\20\15\1\354\24\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\355\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\356\31\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\357\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\17\15\1\360\5\15\1\361\20\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\23\15\1\362\22\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\363\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\364\7\15\1\365\6\15\1\366\23\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\367\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\370\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\26\15\1\371\17\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\1\15\1\372\10\15" - + "\1\373\33\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\21\15\1\374\24\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\6\15\1\375\2\15\1\376\34\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\32\15" - + "\1\377\13\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\21\15\1\u0100\24\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\2\15\1\u0101\43\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u0102\1\15" - + "\1\u0103\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\15\15\1\u0104\1\u0105\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\21\15\1\u0106\24\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u0107" - + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u0108\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\5\15\1\u0109\40\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u010a\44\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u010b" - + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\10\15\1\u010c\35\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\10\15\1\u010d\35\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u010e\42\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u010f" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u0110\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u0111\4\15\1\u0112\2\15\1\u0113" - + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\5\15\1\u0114\40\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\u0115\45\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\3\15\1\u0116\42\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u0117\1\u0118" - + "\1\u0119\6\15\1\u011a\27\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\1\15\1\u011b\44\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u011c\33\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15" - + "\1\u011d\34\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\11\15\1\u011e\34\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\1\15\1\u011f\44\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\44\15\1\u0120\1\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15" - + "\1\u0121\22\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\15\15\1\u0122\30\15\23\0\1\15\15\0\1\u0123" - + "\125\0\1\u0124\3\0\2\u0124\116\0\2\u0125\1\0\4\u0125" - + "\4\0\1\u0125\1\0\2\u0125\1\0\1\u0125\6\0\2\u0125" - + "\12\0\1\u0125\1\0\1\u0125\5\0\2\u0125\47\0\2\u0126" - + "\1\0\4\u0126\4\0\1\u0126\1\0\2\u0126\1\0\1\u0126" - + "\6\0\2\u0126\12\0\1\u0126\1\0\1\u0126\5\0\2\u0126" - + "\36\0\1\u0127\12\0\2\u0127\2\0\1\u0127\4\0\46\u0127" - + "\40\0\1\276\1\277\122\0\1\277\1\0\1\u0128\113\0" - + "\1\u0129\12\0\2\u0129\2\0\1\u0129\4\0\46\u0129\32\0" - + "\1\u012a\1\301\1\u012b\2\0\1\115\1\u012c\2\0\2\301" - + "\2\u012a\2\301\1\u012a\4\0\46\u012a\23\0\1\301\2\0" - + "\1\307\121\0\5\310\1\u012d\116\310\4\0\1\307\1\311" - + "\124\0\2\313\3\0\1\u012e\3\0\7\313\4\0\46\313" - + "\23\0\1\313\6\0\2\314\1\u012f\2\0\1\316\1\u0130" - + "\1\u0131\1\0\7\314\4\0\46\314\23\0\1\314\6\0" - + "\1\u0132\12\0\2\u0132\2\0\1\u0132\4\0\46\u0132\32\0" - + "\1\u0133\5\0\1\317\4\0\2\u0133\2\0\1\u0133\4\0" - + "\46\u0133\41\0\1\u0134\125\0\2\u0135\1\0\4\u0135\4\0" - + "\1\u0135\1\0\2\u0135\1\0\1\u0135\6\0\2\u0135\12\0" - + "\1\u0135\1\0\1\u0135\5\0\2\u0135\41\0\1\133\5\0" - + "\1\u0136\1\144\2\0\2\u0136\1\150\6\0\1\150\106\0" - + "\2\327\2\0\2\327\105\0\2\15\7\0\7\15\4\0" - + "\3\15\1\u0137\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\13\15\1\u0138\32\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\7\15\1\u0139\36\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u013a" - + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\20\15\1\u013b\25\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u013c\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\16\15\1\u013d\27\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u013e" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u013f\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\5\15\1\u0140\40\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\16\15\1\u0141\27\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\u0142" - + "\2\15\1\u0143\34\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0144\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u0145\7\15\1\u0146" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\21\15\1\u0147\24\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0148\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u0149\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u014a" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\15\1\u014b\44\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\16\15\1\u014c\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u014d\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u014e" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u014f\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\5\15\1\u0150\40\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u0151\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u0152" - + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\26\15\1\u0153\17\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\26\15\1\u0154\17\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\7\15\1\u0155\36\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\u0156" - + "\37\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0157\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u0158\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u0159\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u015a" - + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\7\15\1\u015b\6\15\1\u015c\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u015d\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u015e" - + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\3\15\1\u015f\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u0160\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\16\15\1\u0161\27\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0162" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\6\15\1\u0163\37\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\7\15\1\u0164\36\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u0165\42\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\5\15\1\u0166" - + "\40\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\26\15\1\u0167\17\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\14\15\1\u0168\31\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\20\15\1\u0169\25\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u016a" - + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\24\15\1\u016b\21\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u016c\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\10\15\1\u016d\13\15\1\u016e" - + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\4\15\1\u016f\41\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\16\15\1\u0170\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\22\15\1\u0171\23\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\20\15\1\u0172" - + "\25\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\13\15\1\u0173\32\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\15\1\u0174\44\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u0175\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u0176" - + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\27\15\1\u0177\3\15\1\u0178\6\15\1\u0179\3\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u017a" - + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u017b\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\u017c\45\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u017d\33\15\23\0\1\15" - + "\17\0\1\u017e\3\0\2\u017e\116\0\2\u017f\1\0\4\u017f" - + "\4\0\1\u017f\1\0\2\u017f\1\0\1\u017f\6\0\2\u017f" - + "\12\0\1\u017f\1\0\1\u017f\5\0\2\u017f\47\0\2\u0180" - + "\1\0\4\u0180\4\0\1\u0180\1\0\2\u0180\1\0\1\u0180" - + "\6\0\2\u0180\12\0\1\u0180\1\0\1\u0180\5\0\2\u0180" - + "\36\0\2\u0127\4\0\1\276\1\277\1\0\7\u0127\4\0" - + "\46\u0127\23\0\1\u0127\1\u0128\2\0\13\u0128\1\u0181\105\u0128" - + "\6\0\2\u0129\1\u0182\2\0\1\u0183\3\0\7\u0129\4\0" - + "\46\u0129\23\0\1\u0129\6\0\2\u012a\1\u0184\2\0\1\115" - + "\1\u0185\1\u0186\1\0\7\u012a\4\0\46\u012a\23\0\1\u012a" - + "\6\0\1\u0187\12\0\2\u0187\2\0\1\u0187\4\0\46\u0187" - + "\32\0\1\u0188\5\0\1\u012c\4\0\2\u0188\2\0\1\u0188" - + "\4\0\46\u0188\24\0\4\310\1\307\1\u012d\116\310\6\0" - + "\1\u0189\12\0\2\u0189\2\0\1\u0189\4\0\46\u0189\32\0" - + "\1\u0133\5\0\1\u0130\1\u0131\3\0\2\u0133\2\0\1\u0133" - + "\4\0\46\u0133\40\0\1\u0131\1\0\1\u018a\113\0\1\u018b" - + "\1\u0132\3\0\1\316\1\317\2\0\2\u0132\2\u018b\2\u0132" - + "\1\u018b\4\0\46\u018b\23\0\1\u0132\6\0\2\u0133\1\u018c" - + "\3\0\1\u018d\1\u0131\1\0\7\u0133\4\0\46\u0133\23\0" - + "\1\u0133\17\0\2\u018e\1\0\4\u018e\4\0\1\u018e\1\0" - + "\2\u018e\1\0\1\u018e\6\0\2\u018e\12\0\1\u018e\1\0" - + "\1\u018e\5\0\2\u018e\41\0\1\133\5\0\1\u018f\1\144" - + "\2\0\2\u018f\1\150\6\0\1\150\75\0\2\15\7\0" - + "\7\15\4\0\4\15\1\u0190\41\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u0191\44\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\24\15\1\u0192" - + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\7\15\1\u0193\36\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\10\15\1\u0194\35\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\20\15\1\u0195\25\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u0196" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u0197\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0198\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u0199\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\12\15\1\u019a" - + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\30\15\1\u019b\10\15\1\u019c\4\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u019d\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u019e" - + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\5\15\1\u019f\40\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\15\1\u01a0\44\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\12\15\1\u01a1\33\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\32\15\1\u01a2" - + "\13\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\6\15\1\u01a3\37\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u01a4\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\33\15\1\u01a5\12\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u01a6" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u01a7\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\17\15\1\u01a8\26\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\7\15\1\u01a9\36\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u01aa" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\15\1\u01ab\44\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u01ac\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u01ad\44\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u01ae" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\15\15\1\u01af\30\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u01b0\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\13\15\1\u01b1\32\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u01b2" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u01b3\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\23\15\1\u01b4\22\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u01b5\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\23\15\1\u01b6" - + "\22\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u01b7\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u01b8\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u01b9\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\37\15\1\u01ba" - + "\2\15\1\u01bb\3\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u01bc\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\32\15\1\u01bd\13\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u01be" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\11\15\1\u01bf\34\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u01c0\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u01c1\42\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\12\15\1\u01c2" - + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\15\1\u01c3\44\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\u01c4\45\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\14\15\1\u01c5\31\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u01c6\35\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15" - + "\1\u01c7\44\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u01c8\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\2\15\1\u01c9\43\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\30\15\1\u01ca\15\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01cb\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u01cc\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\10\15\1\u01cd\35\15\23\0\1\15" - + "\1\u0128\2\0\11\u0128\1\u0181\1\u0128\1\u0181\105\u0128\6\0" - + "\1\u01ce\12\0\2\u01ce\2\0\1\u01ce\4\0\46\u01ce\32\0" - + "\1\u01cf\12\0\2\u01cf\2\0\1\u01cf\4\0\46\u01cf\32\0" - + "\1\u0188\5\0\1\u0185\1\u0186\3\0\2\u0188\2\0\1\u0188" - + "\4\0\46\u0188\40\0\1\u0186\1\0\1\u01d0\113\0\1\u01d1" - + "\1\u0187\3\0\1\115\1\u012c\2\0\2\u0187\2\u01d1\2\u0187" - + "\1\u01d1\4\0\46\u01d1\23\0\1\u0187\6\0\2\u0188\1\u01d2" - + "\3\0\1\u01d3\1\u0186\1\0\7\u0188\4\0\46\u0188\23\0" - + "\1\u0188\6\0\1\u018b\1\u0189\3\0\1\316\1\u0130\1\u0131" - + "\1\0\2\u0189\2\u018b\2\u0189\1\u018b\4\0\46\u018b\23\0" - + "\1\u0189\1\u018a\2\0\13\u018a\1\u01d4\105\u018a\6\0\2\u018b" - + "\1\u018c\2\0\1\316\1\u0130\1\u0131\1\0\7\u018b\4\0" - + "\46\u018b\23\0\1\u018b\6\0\1\u01d5\12\0\2\u01d5\2\0" - + "\1\u01d5\4\0\46\u01d5\40\0\1\u018d\1\u0131\125\0\2\u01d6" - + "\1\0\4\u01d6\4\0\1\u01d6\1\0\2\u01d6\1\0\1\u01d6" - + "\6\0\2\u01d6\12\0\1\u01d6\1\0\1\u01d6\5\0\2\u01d6" - + "\41\0\1\133\5\0\1\u01d7\1\144\2\0\2\u01d7\1\150" - + "\6\0\1\150\75\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01d8\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u01d9\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\23\15\1\u01da\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u01db\31\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01dc\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\41\15\1\u01dd\4\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\5\15\1\u01de\40\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\16\15\1\u01df\27\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15" - + "\1\u01e0\44\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\u01e1\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\20\15\1\u01e2\25\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u01e3\33\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01e4\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\u01e5\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\21\15\1\u01e6\24\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\3\15\1\u01e7\42\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15" - + "\1\u01e8\34\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u01e9\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\15\15\1\u01ea\30\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u01eb\35\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01ec\4\15\1\u01ed\30\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\23\15\1\u01ee\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u01ef\34\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15" - + "\1\u01f0\22\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u01f1\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\14\15\1\u01f2\31\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\16\15\1\u01f3\27\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u01f4\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\5\15\1\u01f5\40\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u01f6\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u01f7\22\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\u01f8\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u01f9\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\20\15\1\u01fa\25\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\7\15\1\u01fb\36\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\3\15" - + "\1\u01fc\42\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\u01fd\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\5\15\1\u01fe\40\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\30\15\1\u01ff\13\15" - + "\1\u0200\1\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\11\15\1\u0201\34\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\26\15\1\u0202\17\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u0203\40\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\6\15" - + "\1\u0204\37\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\26\15\1\u0205\17\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\16\15\1\u0206\27\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u0207\22\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15" - + "\1\u0208\44\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\10\15\1\u0209\35\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\26\15\1\u020a\17\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\1\15\1\u020b\44\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15" - + "\1\u020c\33\15\23\0\1\15\6\0\2\u01ce\3\0\1\u0183" - + "\3\0\7\u01ce\4\0\46\u01ce\23\0\1\u01ce\6\0\1\u01d1" - + "\1\u01cf\3\0\1\115\1\u0185\1\u0186\1\0\2\u01cf\2\u01d1" - + "\2\u01cf\1\u01d1\4\0\46\u01d1\23\0\1\u01cf\1\u01d0\2\0" - + "\13\u01d0\1\u020d\105\u01d0\6\0\2\u01d1\1\u01d2\2\0\1\115" - + "\1\u0185\1\u0186\1\0\7\u01d1\4\0\46\u01d1\23\0\1\u01d1" - + "\6\0\1\u020e\12\0\2\u020e\2\0\1\u020e\4\0\46\u020e" - + "\40\0\1\u01d3\1\u0186\106\0\1\u018a\2\0\10\u018a\1\u020f" - + "\1\u01d4\1\u018a\1\u01d4\105\u018a\6\0\2\u01d5\4\0\1\u018d" - + "\1\u0131\1\0\7\u01d5\4\0\46\u01d5\23\0\1\u01d5\17\0" - + "\2\u0210\1\0\4\u0210\4\0\1\u0210\1\0\2\u0210\1\0" - + "\1\u0210\6\0\2\u0210\12\0\1\u0210\1\0\1\u0210\5\0" - + "\2\u0210\41\0\1\133\5\0\1\u0211\1\144\2\0\2\u0211" - + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0" - + "\37\15\1\u0212\6\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0213\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\13\15\1\u0214\32\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u0215" - + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u0216\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u0217\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\u0218\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u0219" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\3\15\1\u021a\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u021b\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u021c\44\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\43\15\1\u021d" - + "\2\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\34\15\1\u021e\11\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\5\15\1\u021f\40\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u0220\42\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0221" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0222\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u0223\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\10\15\1\u0224\35\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\37\15\1\u0225" - + "\6\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\11\15\1\u0226\34\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u0227\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\5\15\1\u0228\40\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0229" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\22\15\1\u022a\23\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\7\15\1\u022b\36\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\24\15\1\u022c\21\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u022d" - + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\3\15\1\u022e\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u022f\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\6\15\1\u0230\37\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u0231" - + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0232\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u0233\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u0234\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u0235" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0236\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0237\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\u0238\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u0239" - + "\34\15\23\0\1\15\1\u01d0\2\0\10\u01d0\1\u023a\1\u020d" - + "\1\u01d0\1\u020d\105\u01d0\6\0\2\u020e\4\0\1\u01d3\1\u0186" - + "\1\0\7\u020e\4\0\46\u020e\23\0\1\u020e\17\0\2\u023b" - + "\1\0\4\u023b\4\0\1\u023b\1\0\2\u023b\1\0\1\u023b" - + "\6\0\2\u023b\12\0\1\u023b\1\0\1\u023b\5\0\2\u023b" - + "\41\0\1\133\5\0\1\u023c\1\144\2\0\2\u023c\1\150" - + "\6\0\1\150\75\0\2\15\7\0\7\15\4\0\7\15" - + "\1\u023d\36\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u023e\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\3\15\1\u023f\42\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\31\15\1\u0240\14\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\26\15" - + "\1\u0241\17\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u0242\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\23\15\1\u0243\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u0244\40\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\26\15" - + "\1\u0245\17\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\u0246\42\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u0247\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0248\43\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\u0249\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\5\15\1\u024a\40\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\36\15\1\u024b\7\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u024c\35\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u024d\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\7\15\1\u024e\36\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\11\15\1\u024f\34\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u0250\35\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u0251\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u0252\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u0253\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u0254\22\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u0255\43\15\23\0\1\15\6\0\2\15\7\0\3\15" - + "\1\u0256\3\15\4\0\46\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\23\15\1\u0257\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\1\15\1\u0258\44\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\20\15" - + "\1\u0259\25\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\u025a\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u025b\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\31\15\1\u025c\11\15" - + "\1\u025d\2\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\22\15\1\u025e\23\15\23\0\1\15\17\0\2\u025f" - + "\1\0\4\u025f\4\0\1\u025f\1\0\2\u025f\1\0\1\u025f" - + "\6\0\2\u025f\12\0\1\u025f\1\0\1\u025f\5\0\2\u025f" - + "\41\0\1\133\5\0\1\u0260\1\144\2\0\2\u0260\1\150" - + "\6\0\1\150\75\0\2\15\7\0\7\15\4\0\24\15" - + "\1\u0261\21\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\26\15\1\u0262\17\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\7\15\1\u0263\36\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0264\43\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u0265\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u0266\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\11\15\1\u0267\34\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\26\15\1\u0268\17\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\7\15" - + "\1\u0269\36\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u026a\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\7\15\1\u026b\36\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u026c\34\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15" - + "\1\u026d\31\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\24\15\1\u026e\21\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\2\15\1\u026f\43\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u0270\31\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u0271\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\u0272\42\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\2\15\1\u0273\43\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u0274\31\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15" - + "\1\u0275\33\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u0276\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\7\15\1\u0277\36\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u0278\34\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\u0279\27\15\23\0\1\15\17\0\2\u027a\1\0\4\u027a" - + "\4\0\1\u027a\1\0\2\u027a\1\0\1\u027a\6\0\2\u027a" - + "\12\0\1\u027a\1\0\1\u027a\5\0\2\u027a\41\0\1\133" - + "\5\0\1\u027b\1\144\2\0\2\u027b\1\150\6\0\1\150" - + "\75\0\2\15\7\0\7\15\4\0\12\15\1\u027c\33\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\13\15" - + "\1\u027d\32\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\11\15\1\u027e\34\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\20\15\1\u027f\25\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\20\15\1\u0280\25\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\15\15" - + "\1\u0281\30\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\u0282\42\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\6\15\1\u0283\37\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u0284\33\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\37\15" - + "\1\u0285\6\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\44\15\1\u0286\1\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\1\u0287\45\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u0288\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u0289" - + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\10\15\1\u028a\35\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\7\15\1\u028b\36\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u028c\42\15\23\0" - + "\1\15\11\0\1\133\5\0\1\u028d\1\144\2\0\2\u028d" - + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u028e\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\10\15\1\u028f\35\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\35\15\1\u0290\10\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u0291" - + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0292\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\7\15\1\u0293\36\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\13\15\1\u0294\32\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u0295" - + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\23\15\1\u0296\22\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\26\15\1\u0297\17\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\21\15\1\u0298\24\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\22\15\1\u0299" - + "\23\15\23\0\1\15\11\0\1\133\5\0\1\u029a\1\144" - + "\2\0\2\u029a\1\150\6\0\1\150\75\0\2\15\7\0" - + "\7\15\4\0\40\15\1\u029b\5\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\u029c\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u029d" - + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u029e\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\44\15\1\u029f\1\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\24\15\1\u02a0\21\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\23\15\1\u02a1" - + "\22\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u02a2\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u02a3\42\15\23\0\1\15\11\0" - + "\1\133\5\0\1\u02a4\1\144\2\0\2\u02a4\1\150\6\0" - + "\1\150\75\0\2\15\7\0\7\15\4\0\16\15\1\u02a5" - + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\6\15\1\u02a6\37\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u02a7\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\u02a8\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u02a9" - + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u02aa\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u02ab\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\21\15\1\u02ac\24\15\23\0" - + "\1\15\11\0\1\133\5\0\1\u02ad\1\144\2\0\2\u02ad" - + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u02ae\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\16\15\1\u02af\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\23\15\1\u02b0\22\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u02b1" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\44\15\1\u02b2\1\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\44\15\1\u02b3\1\15\23\0\1\15\11\0" - + "\1\133\5\0\1\u02b4\1\144\2\0\2\u02b4\1\150\6\0" - + "\1\150\75\0\2\15\7\0\7\15\4\0\21\15\1\u02b5" - + "\24\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u02b6\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\40\15\1\u02b7\5\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\13\15\1\u02b8\32\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u02b9" - + "\32\15\23\0\1\15\11\0\1\133\5\0\1\u02ba\1\144" - + "\2\0\2\u02ba\1\150\6\0\1\150\75\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u02bb\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\16\15\1\u02bc\27\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\23\15\1\u02bd" - + "\22\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\23\15\1\u02be\22\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\22\15\1\u02bf\23\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\12\15\1\u02c0\33\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\21\15\1\u02c1" - + "\24\15\23\0\1\15"; + /** the current state of the DFA */ + private int zzState; - private static int[] zzUnpackTrans() { - int[] result = new int[45864]; - int offset = 0; - offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); - return result; - } + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; - private static int zzUnpackTrans(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - int j = offset; /* index in unpacked array */ + /** the textposition at the last accepting state */ + private int zzMarkedPos; - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - value--; - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } + /** the current text position in the buffer */ + private int zzCurrentPos; + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; - private static final int ZZ_NO_MATCH = 1; + /** number of newlines encountered up to the start of the matched text */ + private int yyline; - private static final int ZZ_PUSHBACK_2BIG = 2; + /** the number of characters up to the start of the matched text */ + private int yychar; - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute(); + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; - private static final String ZZ_ATTRIBUTE_PACKED_0 - = "\6\0\1\11\1\1\1\11\11\1\1\11\3\1\2\11" - + "\26\1\10\11\1\1\2\11\5\1\1\11\2\1\2\11" - + "\4\1\1\11\2\1\1\11\1\1\1\11\1\1\1\11" - + "\3\1\1\11\1\1\1\0\3\11\2\0\1\1\1\0" - + "\1\1\2\11\1\1\1\11\3\1\1\0\2\1\1\0" - + "\2\11\75\1\12\11\1\1\6\11\1\1\1\11\1\1" - + "\6\0\2\11\3\1\1\11\2\0\1\11\3\0\1\11" - + "\1\0\1\11\1\1\2\11\4\1\1\0\112\1\1\11" - + "\12\0\1\11\5\0\1\11\111\1\1\11\1\0\1\11" - + "\1\1\1\0\1\11\12\0\100\1\10\0\67\1\2\0" - + "\153\1\1\11\107\1"; + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; - private static int[] zzUnpackAttribute() { - int[] result = new int[705]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /** + * The number of occupied positions in zzBuffer beyond zzEndRead. + * When a lead/high surrogate has been read from the input stream + * into the final zzBuffer position, this will have a value of 1; + * otherwise, it will have a value of 0. + */ + private int zzFinalHighSurrogate = 0; - private static int zzUnpackAttribute(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ + /* user code: */ - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } - - /** - * the input device - */ - private java.io.Reader zzReader; - - /** - * the current state of the DFA - */ - private int zzState; - - /** - * the current lexical state - */ - private int zzLexicalState = YYINITIAL; - - /** - * this buffer contains the current text to be matched and is the source of - * the yytext() string - */ - private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - - /** - * the textposition at the last accepting state - */ - private int zzMarkedPos; - - /** - * the current text position in the buffer - */ - private int zzCurrentPos; - - /** - * startRead marks the beginning of the yytext() string in the buffer - */ - private int zzStartRead; - - /** - * endRead marks the last character in the buffer, that has been read from - * input - */ - private int zzEndRead; - - /** - * number of newlines encountered up to the start of the matched text - */ - private int yyline; - - /** - * the number of characters up to the start of the matched text - */ - private int yychar; - - /** - * the number of characters from the last newline up to the start of the - * matched text - */ - private int yycolumn; - - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; - - /** - * zzAtEOF == true <=> the scanner is at the EOF - */ - private boolean zzAtEOF; - - /** - * denotes if the user-EOF-code has already been executed - */ - private boolean zzEOFDone; - - /** - * The number of occupied positions in zzBuffer beyond zzEndRead. When a - * lead/high surrogate has been read from the input stream into the final - * zzBuffer position, this will have a value of 1; otherwise, it will have a - * value of 0. - */ - private int zzFinalHighSurrogate = 0; - - /* user code: */ StringBuffer string = new StringBuffer(); private static String xmlTagName = ""; @@ -1280,22 +1234,22 @@ public final class ActionScriptLexer { private final List listeners = new ArrayList<>(); - public void addListener(LexListener listener) { + public void addListener(LexListener listener){ listeners.add(listener); } - public void removeListener(LexListener listener) { + public void removeListener(LexListener listener){ listeners.remove(listener); } - public void informListenersLex(ParsedSymbol s) { - for (LexListener l : listeners) { + public void informListenersLex(ParsedSymbol s){ + for(LexListener l:listeners){ l.onLex(s); } } - public void informListenersPushBack(ParsedSymbol s) { - for (LexListener l : listeners) { + public void informListenersPushBack(ParsedSymbol s){ + for(LexListener l:listeners){ l.onPushBack(s); } } @@ -1307,10 +1261,9 @@ public final class ActionScriptLexer { } ParsedSymbol last; - - public ParsedSymbol lex() throws java.io.IOException, ActionParseException { + public ParsedSymbol lex() throws java.io.IOException, ActionParseException{ ParsedSymbol ret = null; - if (!pushedBack.isEmpty()) { + if (!pushedBack.isEmpty()){ ret = last = pushedBack.pop(); } else { ret = last = yylex(); @@ -1319,1284 +1272,1098 @@ public final class ActionScriptLexer { return ret; } - /** - * Creates a new scanner - * - * @param in the java.io.Reader to read input from. - */ - public ActionScriptLexer(java.io.Reader in) { - this.zzReader = in; + + + /** + * Creates a new scanner + * + * @param in the java.io.Reader to read input from. + */ + public ActionScriptLexer(java.io.Reader in) { + this.zzReader = in; + } + + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x110000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 2916) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; } - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char[] zzUnpackCMap(String packed) { - char[] map = new char[0x110000]; - int i = 0; /* index in packed string */ + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { + /* if not: blow it up */ + char newBuffer[] = new char[zzBuffer.length*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + } - int j = 0; /* index in unpacked array */ + /* fill the buffer with new input */ + int requested = zzBuffer.length - zzEndRead; + int totalRead = 0; + while (totalRead < requested) { + int numRead = zzReader.read(zzBuffer, zzEndRead + totalRead, requested - totalRead); + if (numRead == -1) { + break; + } + totalRead += numRead; + } - while (i < 2916) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do { - map[j++] = value; - } while (--count > 0); + if (totalRead > 0) { + zzEndRead += totalRead; + if (totalRead == requested) { /* possibly more input available */ + if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { + --zzEndRead; + zzFinalHighSurrogate = 1; } - return map; + } + return false; } - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { + // totalRead = 0: End of stream + return true; + } - /* first: make room (if you can) */ - if (zzStartRead > 0) { - zzEndRead += zzFinalHighSurrogate; - zzFinalHighSurrogate = 0; - System.arraycopy(zzBuffer, zzStartRead, - zzBuffer, 0, - zzEndRead - zzStartRead); + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ - /* translate stored positions */ - zzEndRead -= zzStartRead; - zzCurrentPos -= zzStartRead; - zzMarkedPos -= zzStartRead; - zzStartRead = 0; - } + if (zzReader != null) + zzReader.close(); + } - /* is the buffer big enough? */ - if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { - /* if not: blow it up */ - char newBuffer[] = new char[zzBuffer.length * 2]; - System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); - zzBuffer = newBuffer; - zzEndRead += zzFinalHighSurrogate; - zzFinalHighSurrogate = 0; - } - /* fill the buffer with new input */ - int requested = zzBuffer.length - zzEndRead; - int totalRead = 0; - while (totalRead < requested) { - int numRead = zzReader.read(zzBuffer, zzEndRead + totalRead, requested - totalRead); - if (numRead == -1) { - break; - } - totalRead += numRead; - } + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * Internal scan buffer is resized down to its initial length, if it has grown. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + zzFinalHighSurrogate = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + if (zzBuffer.length > ZZ_BUFFERSIZE) + zzBuffer = new char[ZZ_BUFFERSIZE]; + } - if (totalRead > 0) { - zzEndRead += totalRead; - if (totalRead == requested) { /* possibly more input available */ - if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { - --zzEndRead; - zzFinalHighSurrogate = 1; - } - } - return false; - } + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } - // totalRead = 0: End of stream - return true; + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; } - /** - * Closes the input stream. - * - * @throws java.io.IOException - */ - public final void yyclose() throws java.io.IOException { - zzAtEOF = true; /* indicate end of file */ + throw new Error(message); + } - zzEndRead = zzStartRead; /* invalidate buffer */ - if (zzReader != null) { - zzReader.close(); - } - } + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); - /** - * Resets the scanner to read from a new input stream. Does not close the - * old reader. - * - * All internal variables are reset, the old input stream - * cannot be reused (internal buffer is discarded and lost). Lexical - * state is set to ZZ_INITIAL. - * - * Internal scan buffer is resized down to its initial length, if it has - * grown. - * - * @param reader the new input stream - */ - public final void yyreset(java.io.Reader reader) { - zzReader = reader; - zzAtBOL = true; - zzAtEOF = false; - zzEOFDone = false; - zzEndRead = zzStartRead = 0; - zzCurrentPos = zzMarkedPos = 0; - zzFinalHighSurrogate = 0; - yyline = yychar = yycolumn = 0; - zzLexicalState = YYINITIAL; - if (zzBuffer.length > ZZ_BUFFERSIZE) { - zzBuffer = new char[ZZ_BUFFERSIZE]; - } - } + zzMarkedPos -= number; + } - /** - * Returns the current lexical state. - * - * @return - */ - public final int yystate() { - return zzLexicalState; - } - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public ParsedSymbol yylex() throws java.io.IOException, ActionParseException { + int zzInput; + int zzAction; - /** - * Returns the text matched by the current regular expression. - * - * @return - */ - public final String yytext() { - return new String(zzBuffer, zzStartRead, zzMarkedPos - zzStartRead); - } + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; - /** - * Returns the character at position pos from the matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. A value from 0 to - * yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer[zzStartRead + pos]; - } + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; - /** - * Returns the length of the matched text region. - * - * @return - */ - public final int yylength() { - return zzMarkedPos - zzStartRead; - } + while (true) { + zzMarkedPosL = zzMarkedPos; - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of yypushback(int) and - * a match-all fallback rule) this method will only be called with things - * that "Can't Possibly Happen". If this method is called, something is - * seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done in error - * fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; - } catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; - } + yychar+= zzMarkedPosL-zzStartRead; - throw new Error(message); - } + zzAction = -1; - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. This number must - * not be greater than yylength()! - */ - public void yypushback(int number) { - if (number > yylength()) { - zzScanError(ZZ_PUSHBACK_2BIG); - } + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; - zzMarkedPos -= number; - } + // set up zzAction for empty match case: + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + } - /** - * Resumes scanning until the next regular expression is matched, the end of - * input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - * @throws com.jpexs.decompiler.flash.action.parser.ActionParseException - */ - public ParsedSymbol yylex() throws java.io.IOException, ActionParseException { - int zzInput; - int zzAction; - - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - char[] zzBufferL = zzBuffer; - char[] zzCMapL = ZZ_CMAP; - - int[] zzTransL = ZZ_TRANS; - int[] zzRowMapL = ZZ_ROWMAP; - int[] zzAttrL = ZZ_ATTRIBUTE; + zzForAction: { while (true) { - zzMarkedPosL = zzMarkedPos; - - yychar += zzMarkedPosL - zzStartRead; - - zzAction = -1; - - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - - zzState = ZZ_LEXSTATE[zzLexicalState]; - - // set up zzAction for empty match case: - int zzAttributes = zzAttrL[zzState]; - if ((zzAttributes & 1) == 1) { - zzAction = zzState; + + if (zzCurrentPosL < zzEndReadL) { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); + } + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; } - - zzForAction: - { - while (true) { - - if (zzCurrentPosL < zzEndReadL) { - zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); - zzCurrentPosL += Character.charCount(zzInput); - } else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } else { - zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); - zzCurrentPosL += Character.charCount(zzInput); - } - } - int zzNext = zzTransL[zzRowMapL[zzState] + zzCMapL[zzInput]]; - if (zzNext == -1) { - break zzForAction; - } - zzState = zzNext; - - zzAttributes = zzAttrL[zzState]; - if ((zzAttributes & 1) == 1) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ((zzAttributes & 8) == 8) { - break zzForAction; - } - } - - } + else { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; - // store back cached position - zzMarkedPos = zzMarkedPosL; + zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 1: { - } - case 186: - break; - case 2: { - yyline++; - } - case 187: - break; - case 3: { /*ignore*/ - - } - case 188: - break; - case 4: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); - } - case 189: - break; - case 5: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); - } - case 190: - break; - case 6: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); - } - case 191: - break; - case 7: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); - } - case 192: - break; - case 8: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); - } - case 193: - break; - case 9: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); - } - case 194: - break; - case 10: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); - } - case 195: - break; - case 11: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); - } - case 196: - break; - case 12: { - string.setLength(0); - yybegin(STRING); - } - case 197: - break; - case 13: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); - } - case 198: - break; - case 14: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); - } - case 199: - break; - case 15: { - string.setLength(0); - yybegin(CHARLITERAL); - } - case 200: - break; - case 16: { - string.setLength(0); - yybegin(OIDENTIFIER); - } - case 201: - break; - case 17: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); - } - case 202: - break; - case 18: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); - } - case 203: - break; - case 19: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); - } - case 204: - break; - case 20: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); - } - case 205: - break; - case 21: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); - } - case 206: - break; - case 22: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); - } - case 207: - break; - case 23: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); - } - case 208: - break; - case 24: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); - } - case 209: - break; - case 25: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); - } - case 210: - break; - case 26: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); - } - case 211: - break; - case 27: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); - } - case 212: - break; - case 28: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); - } - case 213: - break; - case 29: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); - } - case 214: - break; - case 30: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); - } - case 215: - break; - case 31: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); - } - case 216: - break; - case 32: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); - } - case 217: - break; - case 33: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); - } - case 218: - break; - case 34: { - string.append(yytext()); - } - case 219: - break; - case 35: { - yybegin(YYINITIAL); - yyline++; - } - case 220: - break; - case 36: { - yybegin(YYINITIAL); - // length also includes the trailing quote - return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); - } - case 221: - break; - case 37: { - string.append(yytext()); - yyline++; - } - case 222: - break; - case 38: { - yybegin(XML); - string.append(yytext()); - } - case 223: - break; - case 39: { - string.append(yytext()); - yyline++; - } - case 224: - break; - case 40: { - yybegin(YYINITIAL); - // length also includes the trailing quote - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); - } - case 225: - break; - case 41: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); - } - case 226: - break; - case 42: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); - } - case 227: - break; - case 43: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); - } - case 228: - break; - case 44: { - return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); - } - case 229: - break; - case 45: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); - } - case 230: - break; - case 46: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); - } - case 231: - break; - case 47: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); - } - case 232: - break; - case 48: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); - } - case 233: - break; - case 49: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); - } - case 234: - break; - case 50: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); - } - case 235: - break; - case 51: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); - } - case 236: - break; - case 52: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); - } - case 237: - break; - case 53: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); - } - case 238: - break; - case 54: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); - } - case 239: - break; - case 55: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLOR, yytext()); - } - case 240: - break; - case 56: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); - } - case 241: - break; - case 57: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IN, yytext()); - } - case 242: - break; - case 58: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IF, yytext()); - } - case 243: - break; - case 59: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DO, yytext()); - } - case 244: - break; - case 60: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); - } - case 245: - break; - case 61: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); - } - case 246: - break; - case 62: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); - } - case 247: - break; - case 63: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); - } - case 248: - break; - case 64: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); - } - case 249: - break; - case 65: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); - } - case 250: - break; - case 66: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); - } - case 251: - break; - case 67: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); - } - case 252: - break; - case 68: { - string.append('\\'); /*illegal escape sequence*/ - - } - case 253: - break; - case 69: { - string.append('\"'); - } - case 254: - break; - case 70: { - string.append('\\'); - } - case 255: - break; - case 71: { - string.append('\''); - } - case 256: - break; - case 72: { - string.append('\b'); - } - case 257: - break; - case 73: { - string.append('\r'); - } - case 258: - break; - case 74: { - string.append('\n'); - } - case 259: - break; - case 75: { - string.append('\t'); - } - case 260: - break; - case 76: { - string.append('\f'); - } - case 261: - break; - case 77: { - throw new ActionParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); - } - case 262: - break; - case 78: { - string.append('\u00A7'); - } - case 263: - break; - case 79: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); - } - case 264: - break; - case 80: { - string.setLength(0); - yybegin(XML); - String s = yytext(); - s = s.substring(1, s.length() - 1); - if (s.contains(" ")) { - s = s.substring(0, s.indexOf(' ')); - } - xmlTagName = s; - string.append(yytext()); - } - case 265: - break; - case 81: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); - } - case 266: - break; - case 82: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); - } - case 267: - break; - case 83: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); - } - case 268: - break; - case 84: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); - } - case 269: - break; - case 85: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); - } - case 270: - break; - case 86: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLAND, yytext()); - } - case 271: - break; - case 87: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.CHR, yytext()); - } - case 272: - break; - case 88: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SET, yytext()); - } - case 273: - break; - case 89: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.ORD, yytext()); - } - case 274: - break; - case 90: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); - } - case 275: - break; - case 91: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRY, yytext()); - } - case 276: - break; - case 92: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.INT, yytext()); - } - case 277: - break; - case 93: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.USE, yytext()); - } - case 278: - break; - case 94: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FOR, yytext()); - } - case 279: - break; - case 95: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.VAR, yytext()); - } - case 280: - break; - case 96: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.GET, yytext()); - } - case 281: - break; - case 97: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); - } - case 282: - break; - case 98: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); - } - case 283: - break; - case 99: { - String t = yytext(); - return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, t.substring(2, t.length() - 1)); - } - case 284: - break; - case 100: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); - } - case 285: - break; - case 101: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EACH, yytext()); - } - case 286: - break; - case 102: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.ELSE, yytext()); - } - case 287: - break; - case 103: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.EVAL, yytext()); - } - case 288: - break; - case 104: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CASE, yytext()); - } - case 289: - break; - case 105: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.CALL, yytext()); - } - case 290: - break; - case 106: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOP, yytext()); - } - case 291: - break; - case 107: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); - } - case 292: - break; - case 108: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); - } - case 293: - break; - case 109: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); - } - case 294: - break; - case 110: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WITH, yytext()); - } - case 295: - break; - case 111: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PLAY, yytext()); - } - case 296: - break; - case 112: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); - } - case 297: - break; - case 113: { - char val = (char) Integer.parseInt(yytext().substring(1), 8); - string.append(val); - } - case 298: - break; - case 114: { - char val = (char) Integer.parseInt(yytext().substring(2), 16); - string.append(val); - } - case 299: - break; - case 115: { - string.append(yytext()); - String endtagname = yytext(); - endtagname = endtagname.substring(2, endtagname.length() - 1); - if (endtagname.equals(xmlTagName)) { - yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML, string.toString()); - } - } - case 300: - break; - case 116: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.BREAK, yytext()); - } - case 301: - break; - case 117: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CATCH, yytext()); - } - case 302: - break; - case 118: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONST, yytext()); - } - case 303: - break; - case 119: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CLASS, yytext()); - } - case 304: - break; - case 120: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SUPER, yytext()); - } - case 305: - break; - case 121: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TRACE, yytext()); - } - case 306: - break; - case 122: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THROW, yytext()); - } - case 307: - break; - case 123: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); - } - case 308: - break; - case 124: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WHILE, yytext()); - } - case 309: - break; - case 125: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINT, yytext()); - } - case 310: - break; - case 126: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBCHR, yytext()); - } - case 311: - break; - case 127: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBORD, yytext()); - } - case 312: - break; - case 128: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.RETURN, yytext()); - } - case 313: - break; - case 129: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.RANDOM, yytext()); - } - case 314: - break; - case 130: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.STATIC, yytext()); - } - case 315: - break; - case 131: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.SUBSTR, yytext()); - } - case 316: - break; - case 132: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SWITCH, yytext()); - } - case 317: - break; - case 133: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); - } - case 318: - break; - case 134: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPORT, yytext()); - } - case 319: - break; - case 135: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); - } - case 320: - break; - case 136: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LENGTH, yytext()); - } - case 321: - break; - case 137: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PUBLIC, yytext()); - } - case 322: - break; - case 138: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETURL, yytext()); - } - case 323: - break; - case 139: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STRING_OP, yytext()); - } - case 324: - break; - case 140: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.NUMBER_OP, yytext()); - } - case 325: - break; - case 141: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EXTENDS, yytext()); - } - case 326: - break; - case 142: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NEWLINE, yytext()); - } - case 327: - break; - case 143: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DEFAULT, yytext()); - } - case 328: - break; - case 144: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DYNAMIC, yytext()); - } - case 329: - break; - case 145: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FINALLY, yytext()); - } - case 330: - break; - case 146: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PRIVATE, yytext()); - } - case 331: - break; - case 147: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PACKAGE, yytext()); - } - case 332: - break; - case 148: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONTINUE, yytext()); - } - case 333: - break; - case 149: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOPDRAG, yytext()); - } - case 334: - break; - case 150: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.OVERRIDE, yytext()); - } - case 335: - break; - case 151: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERNAL, yytext()); - } - case 336: - break; - case 152: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FUNCTION, yytext()); - } - case 337: - break; - case 153: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTNUM, yytext()); - } - case 338: - break; - case 154: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBLENGTH, yytext()); - } - case 339: - break; - case 155: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETTIMER, yytext()); - } - case 340: - break; - case 156: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); - } - case 341: - break; - case 157: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STARTDRAG, yytext()); - } - case 342: - break; - case 158: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.NEXTFRAME, yytext()); - } - case 343: - break; - case 159: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.NAMESPACE, yytext()); - } - case 344: - break; - case 160: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERFACE, yytext()); - } - case 345: - break; - case 161: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); - } - case 346: - break; - case 162: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.FSCOMMAND, yytext()); - } - case 347: - break; - case 163: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADMOVIE, yytext()); - } - case 348: - break; - case 164: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PREVFRAME, yytext()); - } - case 349: - break; - case 165: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PROTECTED, yytext()); - } - case 350: - break; - case 166: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TELLTARGET, yytext()); - } - case 351: - break; - case 167: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TARGETPATH, yytext()); - } - case 352: - break; - case 168: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); - } - case 353: - break; - case 169: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPLEMENTS, yytext()); - } - case 354: - break; - case 170: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETVERSION, yytext()); - } - case 355: - break; - case 171: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIE, yytext()); - } - case 356: - break; - case 172: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBSUBSTRING, yytext()); - } - case 357: - break; - case 173: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GOTOANDSTOP, yytext()); - } - case 358: - break; - case 174: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GOTOANDPLAY, yytext()); - } - case 359: - break; - case 175: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADMOVIENUM, yytext()); - } - case 360: - break; - case 176: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOPALLSOUNDS, yytext()); - } - case 361: - break; - case 177: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IFFRAMELOADED, yytext()); - } - case 362: - break; - case 178: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADVARIABLES, yytext()); - } - case 363: - break; - case 179: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTASBITMAP, yytext()); - } - case 364: - break; - case 180: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIENUM, yytext()); - } - case 365: - break; - case 181: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.REMOVEMOVIECLIP, yytext()); - } - case 366: - break; - case 182: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADVARIABLESNUM, yytext()); - } - case 367: - break; - case 183: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTASBITMAPNUM, yytext()); - } - case 368: - break; - case 184: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TOGGLEHIGHQUALITY, yytext()); - } - case 369: - break; - case 185: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.DUPLICATEMOVIECLIP, yytext()); - } - case 370: - break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - { - return new ParsedSymbol(SymbolGroup.EOF, SymbolType.EOF, null); - } - } else { - zzScanError(ZZ_NO_MATCH); - } - } } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 1: + { + } + case 187: break; + case 2: + { yyline++; + } + case 188: break; + case 3: + { /*ignore*/ + } + case 189: break; + case 4: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); + } + case 190: break; + case 5: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); + } + case 191: break; + case 6: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); + } + case 192: break; + case 7: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); + } + case 193: break; + case 8: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); + } + case 194: break; + case 9: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); + } + case 195: break; + case 10: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); + } + case 196: break; + case 11: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); + } + case 197: break; + case 12: + { string.setLength(0); + yybegin(STRING); + } + case 198: break; + case 13: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); + } + case 199: break; + case 14: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); + } + case 200: break; + case 15: + { string.setLength(0); + yybegin(CHARLITERAL); + } + case 201: break; + case 16: + { string.setLength(0); + yybegin(OIDENTIFIER); + } + case 202: break; + case 17: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); + } + case 203: break; + case 18: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); + } + case 204: break; + case 19: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); + } + case 205: break; + case 20: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); + } + case 206: break; + case 21: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); + } + case 207: break; + case 22: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); + } + case 208: break; + case 23: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); + } + case 209: break; + case 24: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); + } + case 210: break; + case 25: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); + } + case 211: break; + case 26: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); + } + case 212: break; + case 27: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); + } + case 213: break; + case 28: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); + } + case 214: break; + case 29: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); + } + case 215: break; + case 30: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); + } + case 216: break; + case 31: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); + } + case 217: break; + case 32: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); + } + case 218: break; + case 33: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); + } + case 219: break; + case 34: + { string.append(yytext()); + } + case 220: break; + case 35: + { yybegin(YYINITIAL); yyline++; + } + case 221: break; + case 36: + { yybegin(YYINITIAL); + // length also includes the trailing quote + return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); + } + case 222: break; + case 37: + { string.append(yytext()); yyline++; + } + case 223: break; + case 38: + { yybegin(XML); string.append(yytext()); + } + case 224: break; + case 39: + { string.append(yytext()); yyline++; + } + case 225: break; + case 40: + { yybegin(YYINITIAL); + // length also includes the trailing quote + return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); + } + case 226: break; + case 41: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); + } + case 227: break; + case 42: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); + } + case 228: break; + case 43: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); + } + case 229: break; + case 44: + { return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); + } + case 230: break; + case 45: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); + } + case 231: break; + case 46: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); + } + case 232: break; + case 47: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); + } + case 233: break; + case 48: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); + } + case 234: break; + case 49: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); + } + case 235: break; + case 50: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); + } + case 236: break; + case 51: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); + } + case 237: break; + case 52: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); + } + case 238: break; + case 53: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); + } + case 239: break; + case 54: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); + } + case 240: break; + case 55: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLOR, yytext()); + } + case 241: break; + case 56: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); + } + case 242: break; + case 57: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IN, yytext()); + } + case 243: break; + case 58: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IF, yytext()); + } + case 244: break; + case 59: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DO, yytext()); + } + case 245: break; + case 60: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); + } + case 246: break; + case 61: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); + } + case 247: break; + case 62: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); + } + case 248: break; + case 63: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); + } + case 249: break; + case 64: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); + } + case 250: break; + case 65: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); + } + case 251: break; + case 66: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); + } + case 252: break; + case 67: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); + } + case 253: break; + case 68: + { string.append('\\'); /*illegal escape sequence*/ + } + case 254: break; + case 69: + { string.append('\"'); + } + case 255: break; + case 70: + { string.append('\\'); + } + case 256: break; + case 71: + { string.append('\''); + } + case 257: break; + case 72: + { string.append('\b'); + } + case 258: break; + case 73: + { string.append('\r'); + } + case 259: break; + case 74: + { string.append('\n'); + } + case 260: break; + case 75: + { string.append('\t'); + } + case 261: break; + case 76: + { string.append('\f'); + } + case 262: break; + case 77: + { throw new ActionParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); + } + case 263: break; + case 78: + { string.append('\u00A7'); + } + case 264: break; + case 79: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); + } + case 265: break; + case 80: + { string.setLength(0); + yybegin(XML); + String s = yytext(); + s = s.substring(1, s.length() - 1); + if (s.contains(" ")){ + s = s.substring(0, s.indexOf(' ')); + } + xmlTagName = s; + string.append(yytext()); + } + case 266: break; + case 81: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); + } + case 267: break; + case 82: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); + } + case 268: break; + case 83: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); + } + case 269: break; + case 84: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); + } + case 270: break; + case 85: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); + } + case 271: break; + case 86: + { return new ParsedSymbol(SymbolGroup.PREPROCESSOR, SymbolType.PREPROCESSOR, yytext().substring(2)); + } + case 272: break; + case 87: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLAND, yytext()); + } + case 273: break; + case 88: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.CHR, yytext()); + } + case 274: break; + case 89: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SET, yytext()); + } + case 275: break; + case 90: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.ORD, yytext()); + } + case 276: break; + case 91: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); + } + case 277: break; + case 92: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRY, yytext()); + } + case 278: break; + case 93: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.INT, yytext()); + } + case 279: break; + case 94: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.USE, yytext()); + } + case 280: break; + case 95: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FOR, yytext()); + } + case 281: break; + case 96: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.VAR, yytext()); + } + case 282: break; + case 97: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.GET, yytext()); + } + case 283: break; + case 98: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); + } + case 284: break; + case 99: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); + } + case 285: break; + case 100: + { String t = yytext(); return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, t.substring(2, t.length() - 1)); + } + case 286: break; + case 101: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); + } + case 287: break; + case 102: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EACH, yytext()); + } + case 288: break; + case 103: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.ELSE, yytext()); + } + case 289: break; + case 104: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.EVAL, yytext()); + } + case 290: break; + case 105: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CASE, yytext()); + } + case 291: break; + case 106: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.CALL, yytext()); + } + case 292: break; + case 107: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOP, yytext()); + } + case 293: break; + case 108: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); + } + case 294: break; + case 109: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); + } + case 295: break; + case 110: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); + } + case 296: break; + case 111: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WITH, yytext()); + } + case 297: break; + case 112: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PLAY, yytext()); + } + case 298: break; + case 113: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); + } + case 299: break; + case 114: + { char val = (char) Integer.parseInt(yytext().substring(1), 8); + string.append(val); + } + case 300: break; + case 115: + { char val = (char) Integer.parseInt(yytext().substring(2), 16); + string.append(val); + } + case 301: break; + case 116: + { string.append(yytext()); + String endtagname = yytext(); + endtagname = endtagname.substring(2, endtagname.length() - 1); + if (endtagname.equals(xmlTagName)){ + yybegin(YYINITIAL); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML, string.toString()); + } + } + case 302: break; + case 117: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.BREAK, yytext()); + } + case 303: break; + case 118: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CATCH, yytext()); + } + case 304: break; + case 119: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONST, yytext()); + } + case 305: break; + case 120: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CLASS, yytext()); + } + case 306: break; + case 121: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SUPER, yytext()); + } + case 307: break; + case 122: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TRACE, yytext()); + } + case 308: break; + case 123: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THROW, yytext()); + } + case 309: break; + case 124: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); + } + case 310: break; + case 125: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WHILE, yytext()); + } + case 311: break; + case 126: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINT, yytext()); + } + case 312: break; + case 127: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBCHR, yytext()); + } + case 313: break; + case 128: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBORD, yytext()); + } + case 314: break; + case 129: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.RETURN, yytext()); + } + case 315: break; + case 130: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.RANDOM, yytext()); + } + case 316: break; + case 131: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.STATIC, yytext()); + } + case 317: break; + case 132: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.SUBSTR, yytext()); + } + case 318: break; + case 133: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SWITCH, yytext()); + } + case 319: break; + case 134: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); + } + case 320: break; + case 135: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPORT, yytext()); + } + case 321: break; + case 136: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); + } + case 322: break; + case 137: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LENGTH, yytext()); + } + case 323: break; + case 138: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PUBLIC, yytext()); + } + case 324: break; + case 139: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETURL, yytext()); + } + case 325: break; + case 140: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STRING_OP, yytext()); + } + case 326: break; + case 141: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.NUMBER_OP, yytext()); + } + case 327: break; + case 142: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EXTENDS, yytext()); + } + case 328: break; + case 143: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NEWLINE, yytext()); + } + case 329: break; + case 144: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DEFAULT, yytext()); + } + case 330: break; + case 145: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DYNAMIC, yytext()); + } + case 331: break; + case 146: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FINALLY, yytext()); + } + case 332: break; + case 147: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PRIVATE, yytext()); + } + case 333: break; + case 148: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PACKAGE, yytext()); + } + case 334: break; + case 149: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONTINUE, yytext()); + } + case 335: break; + case 150: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOPDRAG, yytext()); + } + case 336: break; + case 151: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.OVERRIDE, yytext()); + } + case 337: break; + case 152: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERNAL, yytext()); + } + case 338: break; + case 153: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FUNCTION, yytext()); + } + case 339: break; + case 154: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTNUM, yytext()); + } + case 340: break; + case 155: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBLENGTH, yytext()); + } + case 341: break; + case 156: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETTIMER, yytext()); + } + case 342: break; + case 157: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); + } + case 343: break; + case 158: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STARTDRAG, yytext()); + } + case 344: break; + case 159: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.NEXTFRAME, yytext()); + } + case 345: break; + case 160: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.NAMESPACE, yytext()); + } + case 346: break; + case 161: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERFACE, yytext()); + } + case 347: break; + case 162: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); + } + case 348: break; + case 163: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.FSCOMMAND, yytext()); + } + case 349: break; + case 164: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADMOVIE, yytext()); + } + case 350: break; + case 165: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PREVFRAME, yytext()); + } + case 351: break; + case 166: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PROTECTED, yytext()); + } + case 352: break; + case 167: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TELLTARGET, yytext()); + } + case 353: break; + case 168: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TARGETPATH, yytext()); + } + case 354: break; + case 169: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); + } + case 355: break; + case 170: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPLEMENTS, yytext()); + } + case 356: break; + case 171: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETVERSION, yytext()); + } + case 357: break; + case 172: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIE, yytext()); + } + case 358: break; + case 173: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBSUBSTRING, yytext()); + } + case 359: break; + case 174: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GOTOANDSTOP, yytext()); + } + case 360: break; + case 175: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GOTOANDPLAY, yytext()); + } + case 361: break; + case 176: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADMOVIENUM, yytext()); + } + case 362: break; + case 177: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOPALLSOUNDS, yytext()); + } + case 363: break; + case 178: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IFFRAMELOADED, yytext()); + } + case 364: break; + case 179: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADVARIABLES, yytext()); + } + case 365: break; + case 180: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTASBITMAP, yytext()); + } + case 366: break; + case 181: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIENUM, yytext()); + } + case 367: break; + case 182: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.REMOVEMOVIECLIP, yytext()); + } + case 368: break; + case 183: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADVARIABLESNUM, yytext()); + } + case 369: break; + case 184: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTASBITMAPNUM, yytext()); + } + case 370: break; + case 185: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TOGGLEHIGHQUALITY, yytext()); + } + case 371: break; + case 186: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.DUPLICATEMOVIECLIP, yytext()); + } + case 372: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { + return new ParsedSymbol(SymbolGroup.EOF, SymbolType.EOF, null); + } + } + else { + zzScanError(ZZ_NO_MATCH); + } + } } + } + + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java index e6ecc2f5a..f8f203340 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java @@ -1,794 +1,806 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action.parser.script; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.FunctionActionItem; -import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; -import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; -import com.jpexs.decompiler.flash.action.model.operations.Inverted; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPop; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; -import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; -import com.jpexs.decompiler.flash.action.swf7.ActionExtends; -import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.helpers.collections.MyEntry; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.TypeItem; -import com.jpexs.decompiler.graph.model.AndItem; -import com.jpexs.decompiler.graph.model.BreakItem; -import com.jpexs.decompiler.graph.model.CommaExpressionItem; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.DoWhileItem; -import com.jpexs.decompiler.graph.model.DuplicateItem; -import com.jpexs.decompiler.graph.model.ForItem; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.NotItem; -import com.jpexs.decompiler.graph.model.OrItem; -import com.jpexs.decompiler.graph.model.SwitchItem; -import com.jpexs.decompiler.graph.model.TernarOpItem; -import com.jpexs.decompiler.graph.model.WhileItem; -import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class ActionSourceGenerator implements SourceGenerator { - - @Override - public List generate(SourceGeneratorLocalData localData, AndItem item) throws CompilationException { - List ret = new ArrayList<>(); - ret.addAll(generateToActionList(localData, item.leftSide)); - ret.add(new ActionPushDuplicate()); - ret.add(new ActionNot()); - List andExpr = generateToActionList(localData, item.rightSide); - andExpr.add(0, new ActionPop()); - int andExprLen = Action.actionsToBytes(andExpr, false, SWF.DEFAULT_VERSION).length; - ret.add(new ActionIf(andExprLen)); - ret.addAll(andExpr); - return ret; - - } - - @Override - public List generate(SourceGeneratorLocalData localData, OrItem item) throws CompilationException { - List ret = new ArrayList<>(); - ret.addAll(generateToActionList(localData, item.leftSide)); - ret.add(new ActionPushDuplicate()); - List orExpr = generateToActionList(localData, item.rightSide); - orExpr.add(0, new ActionPop()); - int orExprLen = Action.actionsToBytes(orExpr, false, SWF.DEFAULT_VERSION).length; - ret.add(new ActionIf(orExprLen)); - ret.addAll(orExpr); - return ret; - } - - public List toActionList(List items) { - List ret = new ArrayList<>(); - for (GraphSourceItem s : items) { - if (s instanceof Action) { - ret.add((Action) s); - } - } - return ret; - } - - private List nonempty(List list) { - if (list == null) { - return new ArrayList<>(); - } - return list; - } - - private List generateIf(SourceGeneratorLocalData localData, GraphTargetItem expression, List onTrueCmds, List onFalseCmds, boolean ternar) throws CompilationException { - List ret = new ArrayList<>(); - if (expression instanceof Inverted) { - ret.addAll(((Inverted) expression).invert().toSource(localData, this)); - } else { - ret.addAll(expression.toSource(localData, this)); - ret.add(new ActionNot()); - } - List onTrue = null; - List onFalse = null; - if (ternar) { - onTrue = toActionList(onTrueCmds.get(0).toSource(localData, this)); - } else { - onTrue = generateToActionList(localData, onTrueCmds); - } - - if (onFalseCmds != null && !onFalseCmds.isEmpty()) { - if (ternar) { - onFalse = toActionList(onFalseCmds.get(0).toSource(localData, this)); - } else { - onFalse = generateToActionList(localData, onFalseCmds); - } - } - byte[] onTrueBytes = Action.actionsToBytes(onTrue, false, SWF.DEFAULT_VERSION); - int onTrueLen = onTrueBytes.length; - - ActionIf ifaif = new ActionIf(0); - ret.add(ifaif); - ret.addAll(onTrue); - ifaif.setJumpOffset(onTrueLen); - ActionJump ajmp = null; - if (onFalse != null) { - if (!((!nonempty(onTrue).isEmpty()) - && (onTrue.get(onTrue.size() - 1) instanceof ActionJump) - && ((((ActionJump) onTrue.get(onTrue.size() - 1)).isContinue) - || (((ActionJump) onTrue.get(onTrue.size() - 1)).isBreak)))) { - ajmp = new ActionJump(0); - ret.add(ajmp); - onTrueLen += ajmp.getTotalActionLength(); - } - ifaif.setJumpOffset(onTrueLen); - byte[] onFalseBytes = Action.actionsToBytes(onFalse, false, SWF.DEFAULT_VERSION); - int onFalseLen = onFalseBytes.length; - if (ajmp != null) { - ajmp.setJumpOffset(onFalseLen); - } - ret.addAll(onFalse); - } - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, IfItem item) throws CompilationException { - return generateIf(localData, item.expression, item.onTrue, item.onFalse, false); - } - - private void fixLoop(List code, int breakOffset) { - fixLoop(code, breakOffset, Integer.MAX_VALUE); - } - - private void fixLoop(List code, int breakOffset, int continueOffset) { - int pos = 0; - for (Action a : code) { - pos += a.getTotalActionLength(); - if (a instanceof ActionJump) { - ActionJump aj = (ActionJump) a; - if (aj.isContinue && (continueOffset != Integer.MAX_VALUE)) { - aj.setJumpOffset(-pos + continueOffset); - aj.isContinue = false; - } - if (aj.isBreak) { - aj.setJumpOffset(-pos + breakOffset); - aj.isBreak = false; - } - } - } - } - - @Override - public List generate(SourceGeneratorLocalData localData, TernarOpItem item) throws CompilationException { - List onTrue = new ArrayList<>(); - onTrue.add(item.onTrue); - List onFalse = new ArrayList<>(); - onFalse.add(item.onFalse); - return generateIf(localData, item.expression, onTrue, onFalse, true); - } - - @Override - public List generate(SourceGeneratorLocalData localData, WhileItem item) throws CompilationException { - List ret = new ArrayList<>(); - List whileExpr = new ArrayList<>(); - - List ex = new ArrayList<>(item.expression); - if (!ex.isEmpty()) { - GraphTargetItem lastItem = ex.remove(ex.size() - 1); - whileExpr.addAll(generateToActionList(localData, ex)); - whileExpr.addAll(toActionList(lastItem.toSource(localData, this))); //Want result - } - - List whileBody = generateToActionList(localData, item.commands); - whileExpr.add(new ActionNot()); - ActionIf whileaif = new ActionIf(0); - whileExpr.add(whileaif); - ActionJump whileajmp = new ActionJump(0); - whileBody.add(whileajmp); - int whileExprLen = Action.actionsToBytes(whileExpr, false, SWF.DEFAULT_VERSION).length; - int whileBodyLen = Action.actionsToBytes(whileBody, false, SWF.DEFAULT_VERSION).length; - whileajmp.setJumpOffset(-(whileExprLen - + whileBodyLen)); - whileaif.setJumpOffset(whileBodyLen); - ret.addAll(whileExpr); - fixLoop(whileBody, whileBodyLen, -whileExprLen); - ret.addAll(whileBody); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, DoWhileItem item) throws CompilationException { - List ret = new ArrayList<>(); - List doExpr = generateToActionList(localData, item.expression); - List doBody = generateToActionList(localData, item.commands); - - int doBodyLen = Action.actionsToBytes(doBody, false, SWF.DEFAULT_VERSION).length; - int doExprLen = Action.actionsToBytes(doExpr, false, SWF.DEFAULT_VERSION).length; - - ret.addAll(doBody); - ret.addAll(doExpr); - ActionIf doif = new ActionIf(0); - ret.add(doif); - int offset = doBodyLen + doExprLen + doif.getTotalActionLength(); - doif.setJumpOffset(-offset); - fixLoop(doBody, offset, doBodyLen); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException { - List ret = new ArrayList<>(); - List forExpr = generateToActionList(localData, item.expression); - List forBody = generateToActionList(localData, item.commands); - List forFinalCommands = generateToActionList(localData, item.finalCommands); - - forExpr.add(new ActionNot()); - ActionIf foraif = new ActionIf(0); - forExpr.add(foraif); - ActionJump forajmp = new ActionJump(0); - int forajmpLen = forajmp.getTotalActionLength(); - int forExprLen = Action.actionsToBytes(forExpr, false, SWF.DEFAULT_VERSION).length; - int forBodyLen = Action.actionsToBytes(forBody, false, SWF.DEFAULT_VERSION).length; - int forFinalLen = Action.actionsToBytes(forFinalCommands, false, SWF.DEFAULT_VERSION).length; - forajmp.setJumpOffset(-(forExprLen - + forBodyLen + forFinalLen + forajmpLen)); - foraif.setJumpOffset(forBodyLen + forFinalLen + forajmpLen); - ret.addAll(forExpr); - ret.addAll(forBody); - ret.addAll(forFinalCommands); - ret.add(forajmp); - fixLoop(forBody, forBodyLen + forFinalLen + forajmpLen, forBodyLen); - return ret; - } - - private long uniqLast = 0; - - public String uniqId() { - uniqLast++; - return "" + uniqLast; - } - - @Override - public List generate(SourceGeneratorLocalData localData, SwitchItem item) throws CompilationException { - List ret = new ArrayList<>(); - HashMap registerVars = getRegisterVars(localData); - int exprReg = 0; - for (int i = 0; i < 256; i++) { - if (!registerVars.containsValue(i)) { - registerVars.put("__switch" + uniqId(), i); - exprReg = i; - break; - } - } - - ret.addAll(toActionList(item.switchedObject.toSource(localData, this))); - - boolean firstCase = true; - List> caseIfs = new ArrayList<>(); - List> caseCmds = new ArrayList<>(); - List>> caseExprsAll = new ArrayList<>(); - - loopm: - for (int m = 0; m < item.caseValues.size(); m++) { - List> caseExprs = new ArrayList<>(); - List caseIfsOne = new ArrayList<>(); - int mapping = item.valuesMapping.get(m); - for (; m < item.caseValues.size(); m++) { - int newmapping = item.valuesMapping.get(m); - if (newmapping != mapping) { - m--; - break; - } - List curCaseExpr = generateToActionList(localData, item.caseValues.get(m)); - caseExprs.add(curCaseExpr); - if (firstCase) { - curCaseExpr.add(0, new ActionStoreRegister(exprReg)); - } else { - curCaseExpr.add(0, new ActionPush(new RegisterNumber(exprReg))); - } - curCaseExpr.add(new ActionStrictEquals()); - ActionIf aif = new ActionIf(0); - caseIfsOne.add(aif); - curCaseExpr.add(aif); - ret.addAll(curCaseExpr); - firstCase = false; - } - caseExprsAll.add(caseExprs); - caseIfs.add(caseIfsOne); - List caseCmd = generateToActionList(localData, item.caseCommands.get(mapping)); - caseCmds.add(caseCmd); - } - ActionJump defJump = new ActionJump(0); - ret.add(defJump); - List defCmd = new ArrayList<>(); - if (!item.defaultCommands.isEmpty()) { - defCmd = generateToActionList(localData, item.defaultCommands); - } - for (List caseCmd : caseCmds) { - ret.addAll(caseCmd); - } - ret.addAll(defCmd); - - List> exprLengths = new ArrayList<>(); - for (List> caseExprs : caseExprsAll) { - List lengths = new ArrayList<>(); - for (List caseExpr : caseExprs) { - lengths.add(Action.actionsToBytes(caseExpr, false, SWF.DEFAULT_VERSION).length); - } - exprLengths.add(lengths); - } - List caseLengths = new ArrayList<>(); - for (List caseCmd : caseCmds) { - caseLengths.add(Action.actionsToBytes(caseCmd, false, SWF.DEFAULT_VERSION).length); - } - int defLength = Action.actionsToBytes(defCmd, false, SWF.DEFAULT_VERSION).length; - - for (int i = 0; i < caseIfs.size(); i++) { - for (int c = 0; c < caseIfs.get(i).size(); c++) { - int jmpPos = 0; - for (int j = c + 1; j < caseIfs.get(i).size(); j++) { - jmpPos += exprLengths.get(i).get(j); - } - for (int k = i + 1; k < caseIfs.size(); k++) { - for (int m = 0; m < caseIfs.get(k).size(); m++) { - jmpPos += exprLengths.get(k).get(m); - } - } - jmpPos += defJump.getTotalActionLength(); - for (int n = 0; n < i; n++) { - jmpPos += caseLengths.get(n); - } - caseIfs.get(i).get(c).setJumpOffset(jmpPos); - } - } - int defJmpPos = 0; - for (int i = 0; i < caseIfs.size(); i++) { - defJmpPos += caseLengths.get(i); - } - - defJump.setJumpOffset(defJmpPos); - List caseCmdsAll = new ArrayList<>(); - int breakOffset = 0; - for (int i = 0; i < caseCmds.size(); i++) { - caseCmdsAll.addAll(caseCmds.get(i)); - breakOffset += caseLengths.get(i); - } - breakOffset += defLength; - fixLoop(caseCmdsAll, breakOffset); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, NotItem item) throws CompilationException { - if (item.getOriginal() instanceof Inverted) { - GraphTargetItem norig = ((Inverted) item).invert(); - return norig.toSource(localData, this); - } - List ret = new ArrayList<>(); - ret.addAll(item.getOriginal().toSource(localData, this)); - ret.add(new ActionNot()); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, DuplicateItem item) { - List ret = new ArrayList<>(); - ret.add(new ActionPushDuplicate()); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, BreakItem item) { - List ret = new ArrayList<>(); - ActionJump abreak = new ActionJump(0); - abreak.isBreak = true; - ret.add(abreak); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, ContinueItem item) { - List ret = new ArrayList<>(); - ActionJump acontinue = new ActionJump(0); - acontinue.isContinue = true; - ret.add(acontinue); - return ret; - } - - private List generateToActionList(SourceGeneratorLocalData localData, List commands) throws CompilationException { - return toActionList(generate(localData, commands)); - } - - private List generateToActionList(SourceGeneratorLocalData localData, GraphTargetItem command) throws CompilationException { - return toActionList(command.toSource(localData, this)); - } - - @Override - public List generate(SourceGeneratorLocalData localData, List commands) throws CompilationException { - List ret = new ArrayList<>(); - for (GraphTargetItem item : commands) { - ret.addAll(item.toSourceIgnoreReturnValue(localData, this)); - } - return ret; - } - - public HashMap getRegisterVars(SourceGeneratorLocalData localData) { - return localData.registerVars; - } - - public void setRegisterVars(SourceGeneratorLocalData localData, HashMap value) { - localData.registerVars = value; - } - - public void setInFunction(SourceGeneratorLocalData localData, int value) { - localData.inFunction = value; - } - - public int isInFunction(SourceGeneratorLocalData localData) { - return localData.inFunction; - } - - public boolean isInMethod(SourceGeneratorLocalData localData) { - return localData.inMethod; - } - - public void setInMethod(SourceGeneratorLocalData localData, boolean value) { - localData.inMethod = value; - } - - public int getForInLevel(SourceGeneratorLocalData localData) { - return localData.forInLevel; - } - - public void setForInLevel(SourceGeneratorLocalData localData, int value) { - localData.forInLevel = value; - } - - public int getTempRegister(SourceGeneratorLocalData localData) { - HashMap registerVars = getRegisterVars(localData); - for (int tmpReg = 0; tmpReg < 256; tmpReg++) { - if (!registerVars.containsValue(tmpReg)) { - registerVars.put("__temp" + tmpReg, tmpReg); - return tmpReg; - } - } - return 0; //? - } - - public void releaseTempRegister(SourceGeneratorLocalData localData, int tmp) { - HashMap registerVars = getRegisterVars(localData); - registerVars.remove("__temp" + tmp); - } - - private String getName(GraphTargetItem item) { - if (item instanceof VariableActionItem) { - return ((VariableActionItem) item).getVariableName(); - } - if (item instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) item; - return (String) dv.getResult(); - } - if (item instanceof GetVariableActionItem) { - GetVariableActionItem gv = (GetVariableActionItem) item; - return getName(gv.name); - } - if (item instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) item; - return getName(mem.memberName); - } - return null; - } - - private List getVarParts(GraphTargetItem item) { - List ret = new ArrayList<>(); - do { - if (item instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) item; - ret.add(0, getName(mem)); - item = mem.object; - } - } while (item instanceof GetMemberActionItem); - String f = getName(item); - if (f != null) { - ret.add(0, f); - } - return ret; - } - - private int getVarLength(GraphTargetItem item) { - int len = 1; - do { - if (item instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) item; - item = mem.object; - len++; - } - } while (item instanceof GetMemberActionItem); - return len; - } - - private GraphTargetItem removeVarLast(GraphTargetItem item, int cnt) { - item = Helper.deepCopy(item); - - for (int i = 0; i < cnt; i++) { - if (item instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) item; - item = mem.object; - } - } - return item; - } - - private GraphTargetItem addGlobalPrefix(GraphTargetItem item) { - item = Helper.deepCopy(item); - GraphTargetItem first = item; - GetMemberActionItem mem = null; - do { - if (item instanceof GetMemberActionItem) { - mem = (GetMemberActionItem) item; - item = mem.object; - } - } while (item instanceof GetMemberActionItem); - if (item instanceof GetVariableActionItem) { - GetVariableActionItem v = (GetVariableActionItem) item; - item = new GetMemberActionItem(null, new GetVariableActionItem(null, new DirectValueActionItem(null, 0, "_global", new ArrayList())), v.name); - if (mem != null) { - mem.object = item; - } - } - return first; - } - - private List typeToActions(List type, List value) { - List ret = new ArrayList<>(); - if (type.isEmpty()) { - return ret; - } - ret.add(pushConst(type.get(0))); - if (type.size() == 1 && (value != null)) { - ret.addAll(value); - ret.add(new ActionSetVariable()); - } else { - ret.add(new ActionGetVariable()); - } - for (int i = 1; i < type.size(); i++) { - ret.add(pushConst(type.get(i))); - if ((i == type.size() - 1) && (value != null)) { - ret.addAll(value); - ret.add(new ActionSetMember()); - } else { - ret.add(new ActionGetMember()); - } - } - return ret; - } - - private final List constantPool; - - private final int swfVersion; - - public int getSwfVersion() { - return swfVersion; - } - - public ActionSourceGenerator(int swfVersion, List constantPool) { - this.constantPool = constantPool; - this.swfVersion = swfVersion; - } - - public List getConstantPool() { - return constantPool; - } - - public DirectValueActionItem pushConstTargetItem(String s) { - int index = constantPool.indexOf(s); - if (index == -1) { - constantPool.add(s); - index = constantPool.indexOf(s); - } - return new DirectValueActionItem(null, 0, new ConstantIndex(index), constantPool); - } - - public ActionPush pushConst(String s) { - int index = constantPool.indexOf(s); - if (index == -1) { - constantPool.add(s); - index = constantPool.indexOf(s); - } - return new ActionPush(new ConstantIndex(index)); - } - - public List generateTraits(SourceGeneratorLocalData localData, boolean isInterface, GraphTargetItem name, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List functions, List> vars, List staticFunctions, List> staticVars) throws CompilationException { - List extendsStr = getVarParts(extendsVal); - List ret = new ArrayList<>(); - List nameStr = getVarParts(name); - for (int i = 0; i < nameStr.size() - 1; i++) { - List notBody = new ArrayList<>(); - List globalClassTypeStr = new ArrayList<>(); - globalClassTypeStr.add("_global"); - for (int j = 0; j <= i; j++) { - globalClassTypeStr.add(nameStr.get(j)); - } - - List val = new ArrayList<>(); - val.add(new ActionPush((Long) 0L)); - val.add(pushConst("Object")); - val.add(new ActionNewObject()); - notBody.addAll(typeToActions(globalClassTypeStr, val)); - ret.addAll(typeToActions(globalClassTypeStr, null)); - ret.add(new ActionNot()); - ret.add(new ActionNot()); - ret.add(new ActionIf(Action.actionsToBytes(notBody, false, SWF.DEFAULT_VERSION).length)); - ret.addAll(notBody); - } - List ifbody = new ArrayList<>(); - List globalClassTypeStr = new ArrayList<>(); - globalClassTypeStr.add("_global"); - globalClassTypeStr.addAll(nameStr); - - ParsedSymbol s = null; - List constr = new ArrayList<>(); - - if (constructor == null) { - List val = new ArrayList<>(); - val.add(new ActionDefineFunction("", new ArrayList(), 0, SWF.DEFAULT_VERSION)); - if (!isInterface) { - val.add(new ActionStoreRegister(1)); - } - constr.addAll(typeToActions(globalClassTypeStr, val)); - } else { - constr.addAll(toActionList(((FunctionActionItem) constructor).toSource(localData, this))); - constr.add(new ActionStoreRegister(1)); - constr = (typeToActions(globalClassTypeStr, constr)); - } - if (!isInterface) { - for (GraphTargetItem f : staticFunctions) { - FunctionActionItem fi = (FunctionActionItem) f; - ifbody.add(new ActionPush(new RegisterNumber(1/*static*/))); - ifbody.add(new ActionPush(getName(fi.calculatedFunctionName))); - ifbody.addAll(toActionList(fi.toSource(localData, this))); - ifbody.add(new ActionSetMember()); - } - for (GraphTargetItem f : functions) { - FunctionActionItem fi = (FunctionActionItem) f; - ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/))); - ifbody.add(new ActionPush(getName(fi.calculatedFunctionName))); - ifbody.addAll(toActionList(fi.toSource(localData, this))); - ifbody.add(new ActionSetMember()); - } - for (MyEntry en : staticVars) { - ifbody.add(new ActionPush(new RegisterNumber(1/*static*/))); - ifbody.add(new ActionPush(getName(en.getKey()))); - ifbody.addAll(toActionList(en.getValue().toSource(localData, this))); - ifbody.add(new ActionSetMember()); - } - for (MyEntry en : vars) { - ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/))); - ifbody.add(new ActionPush(getName(en.getKey()))); - ifbody.addAll(toActionList(en.getValue().toSource(localData, this))); - ifbody.add(new ActionSetMember()); - } - } - - if (!isInterface) { - ifbody.add(new ActionPush((Long) 1L)); - ifbody.add(new ActionPush(new Null())); - ifbody.addAll(typeToActions(globalClassTypeStr, null)); - ifbody.add(pushConst("prototype")); - ifbody.add(new ActionGetMember()); - ifbody.add(new ActionPush((Long) 3L)); - ifbody.add(pushConst("ASSetPropFlags")); - ifbody.add(new ActionCallFunction()); - } - - if (constr.isEmpty()) { - List val = new ArrayList<>(); - val.add(new ActionDefineFunction("", new ArrayList(), 0, SWF.DEFAULT_VERSION)); - if (!isInterface) { - val.add(new ActionStoreRegister(1)); - } - constr.addAll(typeToActions(globalClassTypeStr, val)); - } - if (!extendsStr.isEmpty()) { - constr.addAll(typeToActions(globalClassTypeStr, null)); - constr.addAll(typeToActions(extendsStr, null)); - constr.add(new ActionExtends()); - } - if (!isInterface) { - constr.add(new ActionPush(new RegisterNumber(1))); - constr.add(pushConst("prototype")); - constr.add(new ActionGetMember()); - constr.add(new ActionStoreRegister(2)); - constr.add(new ActionPop()); - } - - if (!implementsStr.isEmpty()) { - for (GraphTargetItem imp : implementsStr) { - List impList = getVarParts(imp); - List globImp = new ArrayList<>(); - globImp.add("_global"); - globImp.addAll(impList); - constr.addAll(typeToActions(globImp, null)); - } - constr.add(new ActionPush((long) implementsStr.size())); - constr.addAll(typeToActions(globalClassTypeStr, null)); - constr.add(new ActionImplementsOp()); - } - ifbody.addAll(0, constr); - - ret.addAll(typeToActions(globalClassTypeStr, null)); - ret.add(new ActionNot()); - ret.add(new ActionNot()); - ret.add(new ActionIf(Action.actionsToBytes(ifbody, false, SWF.DEFAULT_VERSION).length)); - ret.addAll(ifbody); - ret.add(new ActionPop()); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, CommaExpressionItem item) throws CompilationException { - if (item.commands.isEmpty()) { - return new ArrayList<>(); - } - - //We need to handle commands and last expression separately, otherwise last expression result will be popped - List cmds = new ArrayList<>(item.commands); - GraphTargetItem lastExpr = cmds.remove(cmds.size() - 1); - List ret = new ArrayList<>(); - ret.addAll(generate(localData, cmds)); - ret.addAll(lastExpr.toSource(localData, this)); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException { - //Unsupported in AS1/2 - return new ArrayList<>(); - } - - @Override - public List generateDiscardValue(SourceGeneratorLocalData localData, GraphTargetItem item) throws CompilationException { - List ret = item.toSource(localData, this); - ret.add(new ActionPop()); - return ret; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action.parser.script; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.operations.Inverted; +import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPop; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; +import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; +import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; +import com.jpexs.decompiler.flash.action.swf7.ActionExtends; +import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.collections.MyEntry; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.model.AndItem; +import com.jpexs.decompiler.graph.model.BreakItem; +import com.jpexs.decompiler.graph.model.CommaExpressionItem; +import com.jpexs.decompiler.graph.model.ContinueItem; +import com.jpexs.decompiler.graph.model.DoWhileItem; +import com.jpexs.decompiler.graph.model.DuplicateItem; +import com.jpexs.decompiler.graph.model.FalseItem; +import com.jpexs.decompiler.graph.model.ForItem; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.OrItem; +import com.jpexs.decompiler.graph.model.SwitchItem; +import com.jpexs.decompiler.graph.model.TernarOpItem; +import com.jpexs.decompiler.graph.model.TrueItem; +import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.helpers.Helper; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class ActionSourceGenerator implements SourceGenerator { + + @Override + public List generate(SourceGeneratorLocalData localData, FalseItem item) throws CompilationException { + return GraphTargetItem.toSourceMerge(localData, this, new ActionPush(Boolean.FALSE)); + } + + @Override + public List generate(SourceGeneratorLocalData localData, TrueItem item) throws CompilationException { + return GraphTargetItem.toSourceMerge(localData, this, new ActionPush(Boolean.TRUE)); + } + + @Override + public List generate(SourceGeneratorLocalData localData, AndItem item) throws CompilationException { + List ret = new ArrayList<>(); + ret.addAll(generateToActionList(localData, item.leftSide)); + ret.add(new ActionPushDuplicate()); + ret.add(new ActionNot()); + List andExpr = generateToActionList(localData, item.rightSide); + andExpr.add(0, new ActionPop()); + int andExprLen = Action.actionsToBytes(andExpr, false, SWF.DEFAULT_VERSION).length; + ret.add(new ActionIf(andExprLen)); + ret.addAll(andExpr); + return ret; + + } + + @Override + public List generate(SourceGeneratorLocalData localData, OrItem item) throws CompilationException { + List ret = new ArrayList<>(); + ret.addAll(generateToActionList(localData, item.leftSide)); + ret.add(new ActionPushDuplicate()); + List orExpr = generateToActionList(localData, item.rightSide); + orExpr.add(0, new ActionPop()); + int orExprLen = Action.actionsToBytes(orExpr, false, SWF.DEFAULT_VERSION).length; + ret.add(new ActionIf(orExprLen)); + ret.addAll(orExpr); + return ret; + } + + public List toActionList(List items) { + List ret = new ArrayList<>(); + for (GraphSourceItem s : items) { + if (s instanceof Action) { + ret.add((Action) s); + } + } + return ret; + } + + private List nonempty(List list) { + if (list == null) { + return new ArrayList<>(); + } + return list; + } + + private List generateIf(SourceGeneratorLocalData localData, GraphTargetItem expression, List onTrueCmds, List onFalseCmds, boolean ternar) throws CompilationException { + List ret = new ArrayList<>(); + if (expression instanceof Inverted) { + ret.addAll(((Inverted) expression).invert(null).toSource(localData, this)); + } else { + ret.addAll(expression.toSource(localData, this)); + ret.add(new ActionNot()); + } + List onTrue = null; + List onFalse = null; + if (ternar) { + onTrue = toActionList(onTrueCmds.get(0).toSource(localData, this)); + } else { + onTrue = generateToActionList(localData, onTrueCmds); + } + + if (onFalseCmds != null && !onFalseCmds.isEmpty()) { + if (ternar) { + onFalse = toActionList(onFalseCmds.get(0).toSource(localData, this)); + } else { + onFalse = generateToActionList(localData, onFalseCmds); + } + } + byte[] onTrueBytes = Action.actionsToBytes(onTrue, false, SWF.DEFAULT_VERSION); + int onTrueLen = onTrueBytes.length; + + ActionIf ifaif = new ActionIf(0); + ret.add(ifaif); + ret.addAll(onTrue); + ifaif.setJumpOffset(onTrueLen); + ActionJump ajmp = null; + if (onFalse != null) { + if (!((!nonempty(onTrue).isEmpty()) + && (onTrue.get(onTrue.size() - 1) instanceof ActionJump) + && ((((ActionJump) onTrue.get(onTrue.size() - 1)).isContinue) + || (((ActionJump) onTrue.get(onTrue.size() - 1)).isBreak)))) { + ajmp = new ActionJump(0); + ret.add(ajmp); + onTrueLen += ajmp.getTotalActionLength(); + } + ifaif.setJumpOffset(onTrueLen); + byte[] onFalseBytes = Action.actionsToBytes(onFalse, false, SWF.DEFAULT_VERSION); + int onFalseLen = onFalseBytes.length; + if (ajmp != null) { + ajmp.setJumpOffset(onFalseLen); + } + ret.addAll(onFalse); + } + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, IfItem item) throws CompilationException { + return generateIf(localData, item.expression, item.onTrue, item.onFalse, false); + } + + private void fixLoop(List code, int breakOffset) { + fixLoop(code, breakOffset, Integer.MAX_VALUE); + } + + private void fixLoop(List code, int breakOffset, int continueOffset) { + int pos = 0; + for (Action a : code) { + pos += a.getTotalActionLength(); + if (a instanceof ActionJump) { + ActionJump aj = (ActionJump) a; + if (aj.isContinue && (continueOffset != Integer.MAX_VALUE)) { + aj.setJumpOffset(-pos + continueOffset); + aj.isContinue = false; + } + if (aj.isBreak) { + aj.setJumpOffset(-pos + breakOffset); + aj.isBreak = false; + } + } + } + } + + @Override + public List generate(SourceGeneratorLocalData localData, TernarOpItem item) throws CompilationException { + List onTrue = new ArrayList<>(); + onTrue.add(item.onTrue); + List onFalse = new ArrayList<>(); + onFalse.add(item.onFalse); + return generateIf(localData, item.expression, onTrue, onFalse, true); + } + + @Override + public List generate(SourceGeneratorLocalData localData, WhileItem item) throws CompilationException { + List ret = new ArrayList<>(); + List whileExpr = new ArrayList<>(); + + List ex = new ArrayList<>(item.expression); + if (!ex.isEmpty()) { + GraphTargetItem lastItem = ex.remove(ex.size() - 1); + whileExpr.addAll(generateToActionList(localData, ex)); + whileExpr.addAll(toActionList(lastItem.toSource(localData, this))); //Want result + } + + List whileBody = generateToActionList(localData, item.commands); + whileExpr.add(new ActionNot()); + ActionIf whileaif = new ActionIf(0); + whileExpr.add(whileaif); + ActionJump whileajmp = new ActionJump(0); + whileBody.add(whileajmp); + int whileExprLen = Action.actionsToBytes(whileExpr, false, SWF.DEFAULT_VERSION).length; + int whileBodyLen = Action.actionsToBytes(whileBody, false, SWF.DEFAULT_VERSION).length; + whileajmp.setJumpOffset(-(whileExprLen + + whileBodyLen)); + whileaif.setJumpOffset(whileBodyLen); + ret.addAll(whileExpr); + fixLoop(whileBody, whileBodyLen, -whileExprLen); + ret.addAll(whileBody); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, DoWhileItem item) throws CompilationException { + List ret = new ArrayList<>(); + List doExpr = generateToActionList(localData, item.expression); + List doBody = generateToActionList(localData, item.commands); + + int doBodyLen = Action.actionsToBytes(doBody, false, SWF.DEFAULT_VERSION).length; + int doExprLen = Action.actionsToBytes(doExpr, false, SWF.DEFAULT_VERSION).length; + + ret.addAll(doBody); + ret.addAll(doExpr); + ActionIf doif = new ActionIf(0); + ret.add(doif); + int offset = doBodyLen + doExprLen + doif.getTotalActionLength(); + doif.setJumpOffset(-offset); + fixLoop(doBody, offset, doBodyLen); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException { + List ret = new ArrayList<>(); + List forExpr = generateToActionList(localData, item.expression); + List forBody = generateToActionList(localData, item.commands); + List forFinalCommands = generateToActionList(localData, item.finalCommands); + + forExpr.add(new ActionNot()); + ActionIf foraif = new ActionIf(0); + forExpr.add(foraif); + ActionJump forajmp = new ActionJump(0); + int forajmpLen = forajmp.getTotalActionLength(); + int forExprLen = Action.actionsToBytes(forExpr, false, SWF.DEFAULT_VERSION).length; + int forBodyLen = Action.actionsToBytes(forBody, false, SWF.DEFAULT_VERSION).length; + int forFinalLen = Action.actionsToBytes(forFinalCommands, false, SWF.DEFAULT_VERSION).length; + forajmp.setJumpOffset(-(forExprLen + + forBodyLen + forFinalLen + forajmpLen)); + foraif.setJumpOffset(forBodyLen + forFinalLen + forajmpLen); + ret.addAll(forExpr); + ret.addAll(forBody); + ret.addAll(forFinalCommands); + ret.add(forajmp); + fixLoop(forBody, forBodyLen + forFinalLen + forajmpLen, forBodyLen); + return ret; + } + + private long uniqLast = 0; + + public String uniqId() { + uniqLast++; + return "" + uniqLast; + } + + @Override + public List generate(SourceGeneratorLocalData localData, SwitchItem item) throws CompilationException { + List ret = new ArrayList<>(); + HashMap registerVars = getRegisterVars(localData); + int exprReg = 0; + for (int i = 0; i < 256; i++) { + if (!registerVars.containsValue(i)) { + registerVars.put("__switch" + uniqId(), i); + exprReg = i; + break; + } + } + + ret.addAll(toActionList(item.switchedObject.toSource(localData, this))); + + boolean firstCase = true; + List> caseIfs = new ArrayList<>(); + List> caseCmds = new ArrayList<>(); + List>> caseExprsAll = new ArrayList<>(); + + loopm: + for (int m = 0; m < item.caseValues.size(); m++) { + List> caseExprs = new ArrayList<>(); + List caseIfsOne = new ArrayList<>(); + int mapping = item.valuesMapping.get(m); + for (; m < item.caseValues.size(); m++) { + int newmapping = item.valuesMapping.get(m); + if (newmapping != mapping) { + m--; + break; + } + List curCaseExpr = generateToActionList(localData, item.caseValues.get(m)); + caseExprs.add(curCaseExpr); + if (firstCase) { + curCaseExpr.add(0, new ActionStoreRegister(exprReg)); + } else { + curCaseExpr.add(0, new ActionPush(new RegisterNumber(exprReg))); + } + curCaseExpr.add(new ActionStrictEquals()); + ActionIf aif = new ActionIf(0); + caseIfsOne.add(aif); + curCaseExpr.add(aif); + ret.addAll(curCaseExpr); + firstCase = false; + } + caseExprsAll.add(caseExprs); + caseIfs.add(caseIfsOne); + List caseCmd = generateToActionList(localData, item.caseCommands.get(mapping)); + caseCmds.add(caseCmd); + } + ActionJump defJump = new ActionJump(0); + ret.add(defJump); + List defCmd = new ArrayList<>(); + if (!item.defaultCommands.isEmpty()) { + defCmd = generateToActionList(localData, item.defaultCommands); + } + for (List caseCmd : caseCmds) { + ret.addAll(caseCmd); + } + ret.addAll(defCmd); + + List> exprLengths = new ArrayList<>(); + for (List> caseExprs : caseExprsAll) { + List lengths = new ArrayList<>(); + for (List caseExpr : caseExprs) { + lengths.add(Action.actionsToBytes(caseExpr, false, SWF.DEFAULT_VERSION).length); + } + exprLengths.add(lengths); + } + List caseLengths = new ArrayList<>(); + for (List caseCmd : caseCmds) { + caseLengths.add(Action.actionsToBytes(caseCmd, false, SWF.DEFAULT_VERSION).length); + } + int defLength = Action.actionsToBytes(defCmd, false, SWF.DEFAULT_VERSION).length; + + for (int i = 0; i < caseIfs.size(); i++) { + for (int c = 0; c < caseIfs.get(i).size(); c++) { + int jmpPos = 0; + for (int j = c + 1; j < caseIfs.get(i).size(); j++) { + jmpPos += exprLengths.get(i).get(j); + } + for (int k = i + 1; k < caseIfs.size(); k++) { + for (int m = 0; m < caseIfs.get(k).size(); m++) { + jmpPos += exprLengths.get(k).get(m); + } + } + jmpPos += defJump.getTotalActionLength(); + for (int n = 0; n < i; n++) { + jmpPos += caseLengths.get(n); + } + caseIfs.get(i).get(c).setJumpOffset(jmpPos); + } + } + int defJmpPos = 0; + for (int i = 0; i < caseIfs.size(); i++) { + defJmpPos += caseLengths.get(i); + } + + defJump.setJumpOffset(defJmpPos); + List caseCmdsAll = new ArrayList<>(); + int breakOffset = 0; + for (int i = 0; i < caseCmds.size(); i++) { + caseCmdsAll.addAll(caseCmds.get(i)); + breakOffset += caseLengths.get(i); + } + breakOffset += defLength; + fixLoop(caseCmdsAll, breakOffset); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, NotItem item) throws CompilationException { + if (item.getOriginal() instanceof Inverted) { + GraphTargetItem norig = ((Inverted) item).invert(null); + return norig.toSource(localData, this); + } + List ret = new ArrayList<>(); + ret.addAll(item.getOriginal().toSource(localData, this)); + ret.add(new ActionNot()); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, DuplicateItem item) { + List ret = new ArrayList<>(); + ret.add(new ActionPushDuplicate()); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, BreakItem item) { + List ret = new ArrayList<>(); + ActionJump abreak = new ActionJump(0); + abreak.isBreak = true; + ret.add(abreak); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, ContinueItem item) { + List ret = new ArrayList<>(); + ActionJump acontinue = new ActionJump(0); + acontinue.isContinue = true; + ret.add(acontinue); + return ret; + } + + private List generateToActionList(SourceGeneratorLocalData localData, List commands) throws CompilationException { + return toActionList(generate(localData, commands)); + } + + private List generateToActionList(SourceGeneratorLocalData localData, GraphTargetItem command) throws CompilationException { + return toActionList(command.toSource(localData, this)); + } + + @Override + public List generate(SourceGeneratorLocalData localData, List commands) throws CompilationException { + List ret = new ArrayList<>(); + for (GraphTargetItem item : commands) { + ret.addAll(item.toSourceIgnoreReturnValue(localData, this)); + } + return ret; + } + + public HashMap getRegisterVars(SourceGeneratorLocalData localData) { + return localData.registerVars; + } + + public void setRegisterVars(SourceGeneratorLocalData localData, HashMap value) { + localData.registerVars = value; + } + + public void setInFunction(SourceGeneratorLocalData localData, int value) { + localData.inFunction = value; + } + + public int isInFunction(SourceGeneratorLocalData localData) { + return localData.inFunction; + } + + public boolean isInMethod(SourceGeneratorLocalData localData) { + return localData.inMethod; + } + + public void setInMethod(SourceGeneratorLocalData localData, boolean value) { + localData.inMethod = value; + } + + public int getForInLevel(SourceGeneratorLocalData localData) { + return localData.forInLevel; + } + + public void setForInLevel(SourceGeneratorLocalData localData, int value) { + localData.forInLevel = value; + } + + public int getTempRegister(SourceGeneratorLocalData localData) { + HashMap registerVars = getRegisterVars(localData); + for (int tmpReg = 0; tmpReg < 256; tmpReg++) { + if (!registerVars.containsValue(tmpReg)) { + registerVars.put("__temp" + tmpReg, tmpReg); + return tmpReg; + } + } + return 0; //? + } + + public void releaseTempRegister(SourceGeneratorLocalData localData, int tmp) { + HashMap registerVars = getRegisterVars(localData); + registerVars.remove("__temp" + tmp); + } + + private String getName(GraphTargetItem item) { + if (item instanceof VariableActionItem) { + return ((VariableActionItem) item).getVariableName(); + } + if (item instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) item; + return (String) dv.getResult(); + } + if (item instanceof GetVariableActionItem) { + GetVariableActionItem gv = (GetVariableActionItem) item; + return getName(gv.name); + } + if (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + return getName(mem.memberName); + } + return null; + } + + private List getVarParts(GraphTargetItem item) { + List ret = new ArrayList<>(); + do { + if (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + ret.add(0, getName(mem)); + item = mem.object; + } + } while (item instanceof GetMemberActionItem); + String f = getName(item); + if (f != null) { + ret.add(0, f); + } + return ret; + } + + private int getVarLength(GraphTargetItem item) { + int len = 1; + do { + if (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + item = mem.object; + len++; + } + } while (item instanceof GetMemberActionItem); + return len; + } + + private GraphTargetItem removeVarLast(GraphTargetItem item, int cnt) { + item = Helper.deepCopy(item); + + for (int i = 0; i < cnt; i++) { + if (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + item = mem.object; + } + } + return item; + } + + private GraphTargetItem addGlobalPrefix(GraphTargetItem item) { + item = Helper.deepCopy(item); + GraphTargetItem first = item; + GetMemberActionItem mem = null; + do { + if (item instanceof GetMemberActionItem) { + mem = (GetMemberActionItem) item; + item = mem.object; + } + } while (item instanceof GetMemberActionItem); + if (item instanceof GetVariableActionItem) { + GetVariableActionItem v = (GetVariableActionItem) item; + item = new GetMemberActionItem(null, new GetVariableActionItem(null, new DirectValueActionItem(null, 0, "_global", new ArrayList())), v.name); + if (mem != null) { + mem.object = item; + } + } + return first; + } + + private List typeToActions(List type, List value) { + List ret = new ArrayList<>(); + if (type.isEmpty()) { + return ret; + } + ret.add(pushConst(type.get(0))); + if (type.size() == 1 && (value != null)) { + ret.addAll(value); + ret.add(new ActionSetVariable()); + } else { + ret.add(new ActionGetVariable()); + } + for (int i = 1; i < type.size(); i++) { + ret.add(pushConst(type.get(i))); + if ((i == type.size() - 1) && (value != null)) { + ret.addAll(value); + ret.add(new ActionSetMember()); + } else { + ret.add(new ActionGetMember()); + } + } + return ret; + } + + private final List constantPool; + + private final int swfVersion; + + public int getSwfVersion() { + return swfVersion; + } + + public ActionSourceGenerator(int swfVersion, List constantPool) { + this.constantPool = constantPool; + this.swfVersion = swfVersion; + } + + public List getConstantPool() { + return constantPool; + } + + public DirectValueActionItem pushConstTargetItem(String s) { + int index = constantPool.indexOf(s); + if (index == -1) { + constantPool.add(s); + index = constantPool.indexOf(s); + } + return new DirectValueActionItem(null, 0, new ConstantIndex(index), constantPool); + } + + public ActionPush pushConst(String s) { + int index = constantPool.indexOf(s); + if (index == -1) { + constantPool.add(s); + index = constantPool.indexOf(s); + } + return new ActionPush(new ConstantIndex(index)); + } + + public List generateTraits(SourceGeneratorLocalData localData, boolean isInterface, GraphTargetItem name, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List functions, List> vars, List staticFunctions, List> staticVars) throws CompilationException { + List extendsStr = getVarParts(extendsVal); + List ret = new ArrayList<>(); + List nameStr = getVarParts(name); + for (int i = 0; i < nameStr.size() - 1; i++) { + List notBody = new ArrayList<>(); + List globalClassTypeStr = new ArrayList<>(); + globalClassTypeStr.add("_global"); + for (int j = 0; j <= i; j++) { + globalClassTypeStr.add(nameStr.get(j)); + } + + List val = new ArrayList<>(); + val.add(new ActionPush((Long) 0L)); + val.add(pushConst("Object")); + val.add(new ActionNewObject()); + notBody.addAll(typeToActions(globalClassTypeStr, val)); + ret.addAll(typeToActions(globalClassTypeStr, null)); + ret.add(new ActionNot()); + ret.add(new ActionNot()); + ret.add(new ActionIf(Action.actionsToBytes(notBody, false, SWF.DEFAULT_VERSION).length)); + ret.addAll(notBody); + } + List ifbody = new ArrayList<>(); + List globalClassTypeStr = new ArrayList<>(); + globalClassTypeStr.add("_global"); + globalClassTypeStr.addAll(nameStr); + + ParsedSymbol s = null; + List constr = new ArrayList<>(); + + if (constructor == null) { + List val = new ArrayList<>(); + val.add(new ActionDefineFunction("", new ArrayList(), 0, SWF.DEFAULT_VERSION)); + if (!isInterface) { + val.add(new ActionStoreRegister(1)); + } + constr.addAll(typeToActions(globalClassTypeStr, val)); + } else { + constr.addAll(toActionList(((FunctionActionItem) constructor).toSource(localData, this))); + constr.add(new ActionStoreRegister(1)); + constr = (typeToActions(globalClassTypeStr, constr)); + } + if (!isInterface) { + for (GraphTargetItem f : staticFunctions) { + FunctionActionItem fi = (FunctionActionItem) f; + ifbody.add(new ActionPush(new RegisterNumber(1/*static*/))); + ifbody.add(new ActionPush(getName(fi.calculatedFunctionName))); + ifbody.addAll(toActionList(fi.toSource(localData, this))); + ifbody.add(new ActionSetMember()); + } + for (GraphTargetItem f : functions) { + FunctionActionItem fi = (FunctionActionItem) f; + ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/))); + ifbody.add(new ActionPush(getName(fi.calculatedFunctionName))); + ifbody.addAll(toActionList(fi.toSource(localData, this))); + ifbody.add(new ActionSetMember()); + } + for (MyEntry en : staticVars) { + ifbody.add(new ActionPush(new RegisterNumber(1/*static*/))); + ifbody.add(new ActionPush(getName(en.getKey()))); + ifbody.addAll(toActionList(en.getValue().toSource(localData, this))); + ifbody.add(new ActionSetMember()); + } + for (MyEntry en : vars) { + ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/))); + ifbody.add(new ActionPush(getName(en.getKey()))); + ifbody.addAll(toActionList(en.getValue().toSource(localData, this))); + ifbody.add(new ActionSetMember()); + } + } + + if (!isInterface) { + ifbody.add(new ActionPush((Long) 1L)); + ifbody.add(new ActionPush(new Null())); + ifbody.addAll(typeToActions(globalClassTypeStr, null)); + ifbody.add(pushConst("prototype")); + ifbody.add(new ActionGetMember()); + ifbody.add(new ActionPush((Long) 3L)); + ifbody.add(pushConst("ASSetPropFlags")); + ifbody.add(new ActionCallFunction()); + } + + if (constr.isEmpty()) { + List val = new ArrayList<>(); + val.add(new ActionDefineFunction("", new ArrayList(), 0, SWF.DEFAULT_VERSION)); + if (!isInterface) { + val.add(new ActionStoreRegister(1)); + } + constr.addAll(typeToActions(globalClassTypeStr, val)); + } + if (!extendsStr.isEmpty()) { + constr.addAll(typeToActions(globalClassTypeStr, null)); + constr.addAll(typeToActions(extendsStr, null)); + constr.add(new ActionExtends()); + } + if (!isInterface) { + constr.add(new ActionPush(new RegisterNumber(1))); + constr.add(pushConst("prototype")); + constr.add(new ActionGetMember()); + constr.add(new ActionStoreRegister(2)); + constr.add(new ActionPop()); + } + + if (!implementsStr.isEmpty()) { + for (GraphTargetItem imp : implementsStr) { + List impList = getVarParts(imp); + List globImp = new ArrayList<>(); + globImp.add("_global"); + globImp.addAll(impList); + constr.addAll(typeToActions(globImp, null)); + } + constr.add(new ActionPush((long) implementsStr.size())); + constr.addAll(typeToActions(globalClassTypeStr, null)); + constr.add(new ActionImplementsOp()); + } + ifbody.addAll(0, constr); + + ret.addAll(typeToActions(globalClassTypeStr, null)); + ret.add(new ActionNot()); + ret.add(new ActionNot()); + ret.add(new ActionIf(Action.actionsToBytes(ifbody, false, SWF.DEFAULT_VERSION).length)); + ret.addAll(ifbody); + ret.add(new ActionPop()); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, CommaExpressionItem item) throws CompilationException { + if (item.commands.isEmpty()) { + return new ArrayList<>(); + } + + //We need to handle commands and last expression separately, otherwise last expression result will be popped + List cmds = new ArrayList<>(item.commands); + GraphTargetItem lastExpr = cmds.remove(cmds.size() - 1); + List ret = new ArrayList<>(); + ret.addAll(generate(localData, cmds)); + ret.addAll(lastExpr.toSource(localData, this)); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException { + //Unsupported in AS1/2 + return new ArrayList<>(); + } + + @Override + public List generateDiscardValue(SourceGeneratorLocalData localData, GraphTargetItem item) throws CompilationException { + List ret = item.toSource(localData, this); + ret.add(new ActionPop()); + return ret; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java index 6b162a4fd..afc76fa4f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.parser.script; /** @@ -32,5 +33,6 @@ public enum SymbolGroup { TYPENAME, EOF, GLOBALFUNC, - GLOBALCONST + GLOBALCONST, + PREPROCESSOR } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java index 7e46c3ce5..4493f9c3d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java @@ -1,222 +1,223 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action.parser.script; - -import com.jpexs.decompiler.graph.GraphTargetItem; - -/** - * - * @author JPEXS - */ -public enum SymbolType { - //Keywords - - BREAK, - CASE, - CONTINUE, - DEFAULT, - DO, - WHILE, - ELSE, - FOR, - EACH, - IN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IF, - RETURN, - SUPER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SWITCH, - THROW, - TRY, - CATCH, - FINALLY, - WITH, - DYNAMIC, - INTERNAL, - OVERRIDE, - PRIVATE, - PROTECTED, - PUBLIC, - STATIC, - CLASS, - CONST, - EXTENDS, - FUNCTION(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GET, - IMPLEMENTS, - INTERFACE, - NAMESPACE, - PACKAGE, - SET, - VAR, - IMPORT, - USE, - FALSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NULL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - THIS(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TRUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //Operators - PARENT_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PARENT_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SEMICOLON, - COMMA(GraphTargetItem.PRECEDENCE_COMMA, false), - REST, - DOT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - ASSIGN(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - GREATER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - LOWER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT(GraphTargetItem.PRECEDENCE_UNARY, false), - NEGATE(GraphTargetItem.PRECEDENCE_UNARY, false), - TERNAR(GraphTargetItem.PRECEDENCE_CONDITIONAL, true, true), /*!! ternar !!!*/ - COLON(GraphTargetItem.PRECEDENCE_CONDITIONAL, false),/*!! ternar !!!*/ - EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - LOWER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - GREATER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - AND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), - OR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), - FULLAND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), - FULLOR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), - INCREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false),//OR Unary - DECREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false), //OR Unary - PLUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), - MINUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), //OR Unary - MULTIPLY(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - DIVIDE(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - BITAND(GraphTargetItem.PRECEDENCE_BITWISEAND, true), - BITOR(GraphTargetItem.PRECEDENCE_BITWISEOR, true), - XOR(GraphTargetItem.PRECEDENCE_BITWISEXOR, true), - MODULO(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_LEFT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - ASSIGN_PLUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MINUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MULTIPLY(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_DIVIDE(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITAND(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_XOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MODULO(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_LEFT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - AS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - DELETE(GraphTargetItem.PRECEDENCE_UNARY, false), - INSTANCEOF(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NAMESPACE_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEW(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPEOF(GraphTargetItem.PRECEDENCE_UNARY, false), - VOID, - ATTRIBUTE, - //Other - STRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), - COMMENT, - XML, - IDENTIFIER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - INTEGER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - DOUBLE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - EOF, - TRACE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GETURL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GOTOANDSTOP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEXTFRAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PLAY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PREVFRAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TELLTARGET(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STOP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STOPALLSOUNDS(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TOGGLEHIGHQUALITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - ORD(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CHR(GraphTargetItem.PRECEDENCE_PRIMARY, false), - DUPLICATEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STOPDRAG(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GETTIMER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LOADVARIABLES(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GOTOANDPLAY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - MBORD(GraphTargetItem.PRECEDENCE_PRIMARY, false), - MBCHR(GraphTargetItem.PRECEDENCE_PRIMARY, false), - MBLENGTH(GraphTargetItem.PRECEDENCE_PRIMARY, false), - MBSUBSTRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), - RANDOM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - REMOVEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STARTDRAG(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SUBSTR(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LENGTH(GraphTargetItem.PRECEDENCE_PRIMARY, false), //string.length - INT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TARGETPATH(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NUMBER_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STRING_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - IFFRAMELOADED, - INFINITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - EVAL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - UNDEFINED(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEWLINE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NAN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GETVERSION(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CALL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LOADVARIABLESNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PRINT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PRINTNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PRINTASBITMAP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PRINTASBITMAPNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - UNLOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - UNLOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - FSCOMMAND(GraphTargetItem.PRECEDENCE_PRIMARY, false); - - private int precedence = GraphTargetItem.NOPRECEDENCE; - - private boolean binary = false; - - private boolean rightAssociative = false; - - public boolean isBinary() { - return binary; - } - - public boolean isRightAssociative() { - return rightAssociative; - } - - public int getPrecedence() { - return precedence; - } - - private SymbolType(int precedence, boolean binary) { - this.precedence = precedence; - this.binary = binary; - } - - private SymbolType(int precedence, boolean binary, boolean rightAssociative) { - this.precedence = precedence; - this.binary = binary; - this.rightAssociative = rightAssociative; - } - - private SymbolType() { - - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action.parser.script; + +import com.jpexs.decompiler.graph.GraphTargetItem; + +/** + * + * @author JPEXS + */ +public enum SymbolType { + //Keywords + + BREAK, + CASE, + CONTINUE, + DEFAULT, + DO, + WHILE, + ELSE, + FOR, + EACH, + IN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + IF, + RETURN, + SUPER(GraphTargetItem.PRECEDENCE_PRIMARY, false), + SWITCH, + THROW, + TRY, + CATCH, + FINALLY, + WITH, + DYNAMIC, + INTERNAL, + OVERRIDE, + PRIVATE, + PROTECTED, + PUBLIC, + STATIC, + CLASS, + CONST, + EXTENDS, + FUNCTION(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GET, + IMPLEMENTS, + INTERFACE, + NAMESPACE, + PACKAGE, + SET, + VAR, + IMPORT, + USE, + FALSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NULL(GraphTargetItem.PRECEDENCE_PRIMARY, false), + THIS(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TRUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + //Operators + PARENT_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PARENT_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + CURLY_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), + CURLY_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + BRACKET_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), + BRACKET_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + SEMICOLON, + COMMA(GraphTargetItem.PRECEDENCE_COMMA, false), + REST, + DOT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + ASSIGN(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + GREATER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + LOWER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + NOT(GraphTargetItem.PRECEDENCE_UNARY, false), + NEGATE(GraphTargetItem.PRECEDENCE_UNARY, false), + TERNAR(GraphTargetItem.PRECEDENCE_CONDITIONAL, true, true), /*!! ternar !!!*/ + COLON(GraphTargetItem.PRECEDENCE_CONDITIONAL, false),/*!! ternar !!!*/ + EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), + STRICT_EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), + LOWER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + GREATER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), + STRICT_NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), + AND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), + OR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), + FULLAND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), + FULLOR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), + INCREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false),//OR Unary + DECREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false), //OR Unary + PLUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), + MINUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), //OR Unary + MULTIPLY(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), + DIVIDE(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), + BITAND(GraphTargetItem.PRECEDENCE_BITWISEAND, true), + BITOR(GraphTargetItem.PRECEDENCE_BITWISEOR, true), + XOR(GraphTargetItem.PRECEDENCE_BITWISEXOR, true), + MODULO(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), + SHIFT_LEFT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), + SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), + USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), + ASSIGN_PLUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_MINUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_MULTIPLY(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_DIVIDE(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_BITAND(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_BITOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_XOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_MODULO(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_SHIFT_LEFT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + AS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + DELETE(GraphTargetItem.PRECEDENCE_UNARY, false), + INSTANCEOF(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + IS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + NAMESPACE_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NEW(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TYPEOF(GraphTargetItem.PRECEDENCE_UNARY, false), + VOID, + ATTRIBUTE, + //Other + STRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), + COMMENT, + XML, + IDENTIFIER(GraphTargetItem.PRECEDENCE_PRIMARY, false), + INTEGER(GraphTargetItem.PRECEDENCE_PRIMARY, false), + DOUBLE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TYPENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), + EOF, + TRACE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GETURL(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GOTOANDSTOP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NEXTFRAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PLAY(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PREVFRAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TELLTARGET(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STOP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STOPALLSOUNDS(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TOGGLEHIGHQUALITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), + ORD(GraphTargetItem.PRECEDENCE_PRIMARY, false), + CHR(GraphTargetItem.PRECEDENCE_PRIMARY, false), + DUPLICATEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STOPDRAG(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GETTIMER(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LOADVARIABLES(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GOTOANDPLAY(GraphTargetItem.PRECEDENCE_PRIMARY, false), + MBORD(GraphTargetItem.PRECEDENCE_PRIMARY, false), + MBCHR(GraphTargetItem.PRECEDENCE_PRIMARY, false), + MBLENGTH(GraphTargetItem.PRECEDENCE_PRIMARY, false), + MBSUBSTRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), + RANDOM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + REMOVEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STARTDRAG(GraphTargetItem.PRECEDENCE_PRIMARY, false), + SUBSTR(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LENGTH(GraphTargetItem.PRECEDENCE_PRIMARY, false), //string.length + INT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TARGETPATH(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NUMBER_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STRING_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + IFFRAMELOADED, + INFINITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), + EVAL(GraphTargetItem.PRECEDENCE_PRIMARY, false), + UNDEFINED(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NEWLINE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NAN(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GETVERSION(GraphTargetItem.PRECEDENCE_PRIMARY, false), + CALL(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LOADVARIABLESNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PRINT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PRINTNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PRINTASBITMAP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PRINTASBITMAPNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + UNLOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + UNLOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + FSCOMMAND(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PREPROCESSOR(GraphTargetItem.PRECEDENCE_PRIMARY, false); + + private int precedence = GraphTargetItem.NOPRECEDENCE; + + private boolean binary = false; + + private boolean rightAssociative = false; + + public boolean isBinary() { + return binary; + } + + public boolean isRightAssociative() { + return rightAssociative; + } + + public int getPrecedence() { + return precedence; + } + + private SymbolType(int precedence, boolean binary) { + this.precedence = precedence; + this.binary = binary; + } + + private SymbolType(int precedence, boolean binary, boolean rightAssociative) { + this.precedence = precedence; + this.binary = binary; + this.rightAssociative = rightAssociative; + } + + private SymbolType() { + + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java index 93f887a6c..339791567 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.swf4; import com.jpexs.decompiler.flash.action.Action; @@ -36,6 +37,6 @@ public class ActionNot extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { GraphTargetItem a = stack.pop(); - stack.push(new NotItem(this, a)); + stack.push(a.invert(this)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java index 4156119da..d95cc43c2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.swf4; import com.jpexs.decompiler.flash.action.Action; @@ -35,13 +36,7 @@ public class ActionPop extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { - if (stack.isEmpty()) { - return; - } GraphTargetItem val = stack.pop(); - if (val instanceof DirectValueActionItem) { - return; - } output.add(val); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java index ab88fd0e1..9b9a790f0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java @@ -37,6 +37,8 @@ import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.FalseItem; +import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.helpers.Helper; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -360,18 +362,27 @@ public class ActionPush extends Action { } } }*/ - DirectValueActionItem dvt = new DirectValueActionItem(this, pos, o, constantPool); - - if (o instanceof RegisterNumber) {//TemporaryRegister - dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); - if (regNames.containsKey(((RegisterNumber) o).number)) { - ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); + if (o instanceof Boolean) { + Boolean b = (Boolean) o; + if (b) { + stack.push(new TrueItem(this)); + } else { + stack.push(new FalseItem(this)); } - } - if (dvt.computedRegValue instanceof TemporaryRegister) { - stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value)); } else { - stack.push(dvt); + DirectValueActionItem dvt = new DirectValueActionItem(this, pos, o, constantPool); + + if (o instanceof RegisterNumber) {//TemporaryRegister + dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); + if (regNames.containsKey(((RegisterNumber) o).number)) { + ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); + } + } + if (dvt.computedRegValue instanceof TemporaryRegister) { + stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value)); + } else { + stack.push(dvt); + } } pos++; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java index c70d93bb4..fb5e7bf96 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.swf5; import com.jpexs.decompiler.flash.action.Action; @@ -39,7 +40,7 @@ public class ActionEnumerate extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { GraphTargetItem object = stack.pop(); - stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); - stack.push(new EnumerateActionItem(this, object)); + //stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); + output.add(new EnumerateActionItem(this, object)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java index 5ffa6770f..f00e5bc70 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java @@ -12,13 +12,15 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.swf5; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.graph.GraphSourceItemPos; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.DuplicateItem; import java.util.HashMap; import java.util.List; @@ -36,7 +38,7 @@ public class ActionPushDuplicate extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { GraphTargetItem value = stack.peek(); - stack.push(value); + stack.push(new DuplicateItem(this, value)); value.moreSrc.add(new GraphSourceItemPos(this, 0)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java index fd05ef6e7..9e56b1868 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java @@ -1,42 +1,42 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action.swf6; - -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class ActionEnumerate2 extends Action { - - public ActionEnumerate2() { - super(0x55, 0); - } - - @Override - public String toString() { - return "Enumerate2"; - } - - @Override - public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { - GraphTargetItem object = stack.pop(); - stack.push(new EnumerateActionItem(this, object)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action.swf6; + +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class ActionEnumerate2 extends Action { + + public ActionEnumerate2() { + super(0x55, 0); + } + + @Override + public String toString() { + return "Enumerate2"; + } + + @Override + public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { + GraphTargetItem object = stack.pop(); + output.add(new EnumerateActionItem(this, object)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 620b9dd18..ad8d72a54 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -16,6 +16,8 @@ */ package com.jpexs.decompiler.graph; +import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.flash.BaseLocalData; import com.jpexs.decompiler.flash.FinalProcessLocalData; import com.jpexs.decompiler.flash.action.Action; @@ -25,7 +27,9 @@ import com.jpexs.decompiler.graph.model.AndItem; import com.jpexs.decompiler.graph.model.BreakItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.DoWhileItem; +import com.jpexs.decompiler.graph.model.DuplicateItem; import com.jpexs.decompiler.graph.model.ExitItem; +import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.ForItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.IntegerValueItem; @@ -37,8 +41,10 @@ import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.ScriptEndItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; +import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.decompiler.graph.model.UniversalLoopItem; import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.helpers.Helper; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -422,7 +428,7 @@ public class Graph { for (GraphPart head : heads) { populateParts(head, allParts); } - TranslateStack stack = new TranslateStack(); + TranslateStack stack = new TranslateStack(path); List loops = new ArrayList<>(); getLoops(localData, heads.get(0), loops, null); /*System.out.println(""); @@ -461,8 +467,59 @@ public class Graph { finalProcessAfter(list, level, localData); } - protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData) { + private boolean processSubBlk(Block b, GraphTargetItem replacement) { + boolean allSubPush = true; + boolean atleastOne = false; + for (List sub : b.getSubs()) { + if (!sub.isEmpty()) { + int lastPos = sub.size() - 1; + GraphTargetItem last = sub.get(sub.size() - 1); + GraphTargetItem br = null; + + if ((last instanceof BreakItem) && (sub.size() >= 2)) { + br = last; + lastPos--; + last = sub.get(lastPos); + } + if (last instanceof Block) { + if (!processSubBlk((Block) last, replacement)) { + allSubPush = false; + } else { + atleastOne = true; + } + } else if (last instanceof PushItem) { + if (replacement != null) { + GraphTargetItem e2 = (((GraphTargetItem) replacement).clone()); + e2.value = last.value; + sub.set(lastPos, e2); + if (br != null) { + sub.remove(sub.size() - 1); + } + } + atleastOne = true; + } else if (!(last instanceof ExitItem)) { + allSubPush = false; + } + } + } + return allSubPush && atleastOne; + } + + protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData) { + if (list.size() >= 2) { + if (list.get(list.size() - 1) instanceof ExitItem) { + ExitItem e = (ExitItem) list.get(list.size() - 1); + if (list.get(list.size() - 1).value instanceof PopItem) { + if (list.get(list.size() - 2) instanceof Block) { + Block b = (Block) list.get(list.size() - 2); + if (processSubBlk(b, (GraphTargetItem) e)) { + list.remove(list.size() - 1); + } + } + } + } + } } protected void finalProcess(List list, int level, FinalProcessLocalData localData) { @@ -527,7 +584,7 @@ public class Graph { } private void processIfs(List list) { - //if(true) return; + for (int i = 0; i < list.size(); i++) { GraphTargetItem item = list.get(i); if (item instanceof Block) { @@ -1382,7 +1439,11 @@ public class Graph { } List currentRet = ret; UniversalLoopItem loopItem = null; + TranslateStack sPreLoop = stack; if (isLoop) { + //makeAllCommands(currentRet, stack); + stack = (TranslateStack) stack.clone(); + stack.clear(); loopItem = new UniversalLoopItem(null, currentLoop); //loopItem.commands=printGraph(visited, localData, stack, allParts, parent, part, stopPart, loops); currentRet.add(loopItem); @@ -1412,23 +1473,6 @@ public class Graph { } } - //Assuming part with two nextparts is an IF - - /* //If with both branches empty - if (part.nextParts.size() == 2) { - if (part.nextParts.get(0) == part.nextParts.get(1)) { - if (!stack.isEmpty()) { - GraphTargetItem expr = stack.pop(); - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } - output.add(new IfItem(null, expr, new ArrayList(), new ArrayList())); - } - part.nextParts.remove(0); - } - }*/ if (parseNext) { List retCheck = check(code, localData, allParts, stack, parent, part, stopPart, loops, output, currentLoop, staticOperation, path); if (retCheck != null) { @@ -1441,134 +1485,15 @@ public class Graph { currentRet.addAll(output); } } - - /** - * AND / OR detection - */ - if (parseNext && part.nextParts.size() == 2) { - if ((stack.size() >= 2) && (stack.get(stack.size() - 1) instanceof NotItem) && (((NotItem) (stack.get(stack.size() - 1))).getOriginal().getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { - GraphPart sp0 = getNextNoJump(part.nextParts.get(0), localData); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1), localData); - boolean reversed = false; - loopContinues = getLoopsContinues(loops); - loopContinues.add(part);//??? - if (sp1.leadsTo(localData, this, code, sp0, loops)) { - } else if (sp0.leadsTo(localData, this, code, sp1, loops)) { - reversed = true; - } - GraphPart next = reversed ? sp0 : sp1; - GraphTargetItem ti; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - List stopPart2 = new ArrayList<>(stopPart); - GraphPart andOrStopPart = reversed ? sp1 : sp0; - stopPart2.add(andOrStopPart); - GraphTargetItem first = ((NotItem) stack.pop()).getOriginal(); - stack.pop(); - stack.push(new MarkItem("disposable")); - printGraph(visited, localData, stack, allParts, parent, next, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); - GraphTargetItem second = stack.pop(); - - if (!reversed) { - AndItem a = new AndItem(null, first, second); - stack.push(a); - a.firstPart = part; - if (second instanceof AndItem) { - a.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - a.firstPart = ((OrItem) second).firstPart; - } - } else { - OrItem o = new OrItem(null, first, second); - stack.push(o); - o.firstPart = part; - if (second instanceof AndItem) { - o.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - o.firstPart = ((OrItem) second).firstPart; - } - } - next = reversed ? sp1 : sp0; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - currentRet.addAll(printGraph(visited, localData, stack, allParts, parent, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); - } - } - parseNext = false; - //return ret; - } else if ((stack.size() >= 2) && (stack.get(stack.size() - 1).getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { - GraphPart sp0 = getNextNoJump(part.nextParts.get(0), localData); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1), localData); - boolean reversed = false; - loopContinues = getLoopsContinues(loops); - loopContinues.add(part);//??? - if (sp1.leadsTo(localData, this, code, sp0, loops)) { - } else if (sp0.leadsTo(localData, this, code, sp1, loops)) { - reversed = true; - } - GraphPart next = reversed ? sp0 : sp1; - GraphTargetItem ti; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - List stopPart2 = new ArrayList<>(stopPart); - GraphPart andOrStopPart = reversed ? sp1 : sp0; - //andOrStopPart.stopPartType = GraphPart.StopPartType.AND_OR; - stopPart2.add(andOrStopPart); - GraphTargetItem first = stack.pop(); - stack.pop(); - stack.push(new MarkItem("disposable")); - printGraph(visited, localData, stack, allParts, parent, next, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); - //stack = andOrStopPart.andOrStack; // Use stack that was stored upon reaching AND_OR stopPart - GraphTargetItem second = stack.pop(); - //GraphTargetItem first = stack.pop(); - //andOrStopPart.stopPartType = GraphPart.StopPartType.NONE; // Reset stopPartType - - if (reversed) { - AndItem a = new AndItem(null, first, second); - stack.push(a); - a.firstPart = part; - if (second instanceof AndItem) { - a.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - a.firstPart = ((OrItem) second).firstPart; - } - } else { - OrItem o = new OrItem(null, first, second); - stack.push(o); - o.firstPart = part; - if (second instanceof OrItem) { - o.firstPart = ((OrItem) second).firstPart; - } - if (second instanceof AndItem) { - o.firstPart = ((AndItem) second).firstPart; - } - } - - next = reversed ? sp1 : sp0; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - currentRet.addAll(printGraph(visited, localData, stack, allParts, parent, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); - } - } - parseNext = false; - //return ret; - } - } //********************************END PART DECOMPILING - if (parseNext) { if (part.nextParts.size() > 2) {//direct switch, seen in the wild... GraphPart next = getMostCommonPart(localData, part.nextParts, loops); List vis = new ArrayList<>(); GraphTargetItem switchedItem = stack.pop(); + makeAllCommands(currentRet, stack); + List caseValues = new ArrayList<>(); List> caseCommands = new ArrayList<>(); List defaultCommands = new ArrayList<>(); @@ -1604,10 +1529,15 @@ public class Graph { } } if (next != p) { + //int stackLenBefore = stack.size(); + TranslateStack s2 = (TranslateStack) stack.clone(); + s2.clear(); + List nextCommands = printGraph(visited, prepareBranchLocalData(localData), s2, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + makeAllCommands(nextCommands, s2); if (first) { - defaultCommands = printGraph(visited, prepareBranchLocalData(localData), stack, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + defaultCommands = nextCommands; } else { - caseCommands.add(printGraph(visited, prepareBranchLocalData(localData), stack, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1)); + caseCommands.add(nextCommands); } vis.add(p); } @@ -1623,41 +1553,23 @@ public class Graph { GraphPart nextOnePart = null; if (part.nextParts.size() == 2) { GraphTargetItem expr = stack.pop(); - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } - if (staticOperation != SOP_USE_STATIC) { - if (expr.isCompileTime()) { - boolean doJump = EcmaScript.toBoolean(expr.getResult()); - if (doJump) { - nextOnePart = part.nextParts.get(0); - } else { - nextOnePart = part.nextParts.get(1); - } - if (staticOperation == SOP_REMOVE_STATIC) { - //TODO - } - } - } + /*if (expr instanceof LogicalOpItem) { + expr = ((LogicalOpItem) expr).invert(); + } else { + expr = new NotItem(null, expr); + }*/ if (nextOnePart == null) { List nps; - /*nps = new ArrayList<>(part.nextParts); - for(int i=0;i onTrue = new ArrayList<>(); + trueStack.clear(); + falseStack.clear(); + /*int trueStackSizeBefore = trueStack.size(); + int falseStackSizeBefore = falseStack.size(); + */ boolean isEmpty = nps.get(0) == nps.get(1); if (isEmpty) { @@ -1665,59 +1577,63 @@ public class Graph { } List stopPart2 = new ArrayList<>(stopPart); - //GraphPart.CommonPartStack commonPartStack = null; + if ((!isEmpty) && (next != null)) { - /*commonPartStack = next.new CommonPartStack(); - if (next.commonPartStacks == null) { - next.commonPartStacks = new ArrayList<>(); - } - next.stopPartType = GraphPart.StopPartType.COMMONPART; - */ stopPart2.add(next); } + List onTrue = new ArrayList<>(); if (!isEmpty) { onTrue = printGraph(visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); } List onFalse = new ArrayList<>(); if (!isEmpty) { - /*if (next != null) { - commonPartStack.isTrueStack = false; //stopPart must know it needs to store falseStack - }*/ onFalse = printGraph(visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); } + //List out2 = new ArrayList<>(); + //makeAllCommands(out2, stack); + makeAllCommands(onTrue, trueStack); + makeAllCommands(onFalse, falseStack); - /* if there is a stopPart (next), then Graph will be further analyzed starting from the stopPart: - * trueStack and falseStack must be set equal to corresponding stack that was built upon reaching stopPart. - if ((!isEmpty) && (next != null)) { - if ((commonPartStack.trueStack != null) && (commonPartStack.falseStack != null)) { - trueStack = commonPartStack.trueStack; - falseStack = commonPartStack.falseStack; - } - next.commonPartStacks.remove(next.commonPartStacks.size() - 1); - if (next.commonPartStacks.isEmpty()) { - next.stopPartType = GraphPart.StopPartType.NONE; // reset StopPartType - } - }*/ - if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() == trueStackSizeBefore + 1) && (falseStack.size() == falseStackSizeBefore + 1)) { - stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop())); + if (!isEmpty(onTrue) && !isEmpty(onFalse) && onTrue.size() == 1 && onFalse.size() == 1 && (onTrue.get(0) instanceof PushItem) && (onFalse.get(0) instanceof PushItem)) { + stack.push(new TernarOpItem(null, expr.invert(null), ((PushItem) onTrue.get(0)).value, ((PushItem) onFalse.get(0)).value)); } else { - currentRet.add(new IfItem(null, expr, onTrue, onFalse)); - } - if (next != null) { - if (trueStack.size() != trueStackSizeBefore || falseStack.size() != falseStackSizeBefore) { - // it's a hack, because duplicates all instructions in the next part, but better than EmptyStackException - onTrue = printGraph(visited, localData, trueStack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1); - onFalse = printGraph(visited, localData, falseStack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1); - if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() == trueStackSizeBefore + 1) && (falseStack.size() == falseStackSizeBefore + 1)) { - stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop())); + boolean isIf = true; + if (!stack.isEmpty() && onFalse.isEmpty() && onTrue.size() == 2 && (onTrue.get(0) instanceof PopItem) && (onTrue.get(1) instanceof PushItem)) { + GraphTargetItem prevExpr = stack.pop(); + GraphTargetItem leftSide = expr; + + GraphTargetItem rightSide = ((PushItem) onTrue.get(1)).value; + if (leftSide instanceof DuplicateItem) { + isIf = false; + stack.push(new OrItem(null, prevExpr, rightSide)); + } else if (leftSide.invert(null) instanceof DuplicateItem) { + isIf = false; + stack.push(new AndItem(null, prevExpr, rightSide)); + } else if (prevExpr instanceof FalseItem) { + isIf = false; + stack.push(new OrItem(null, leftSide, rightSide)); + } else if (prevExpr instanceof TrueItem) { + isIf = false; + stack.push(new AndItem(null, leftSide, rightSide)); } else { - currentRet.add(new IfItem(null, expr, onTrue, onFalse)); + //:-( } - } else { - printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1); } + + if (isIf) { + makeAllCommands(currentRet, stack); + IfItem b = new IfItem(null, expr.invert(null), onTrue, onFalse); + currentRet.add(b); + if (processSubBlk(b, null)) { + stack.push(new PopItem(null)); + } + } + } + //currentRet.addAll(out2); + if (next != null) { + printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1); //currentRet.addAll(); } } @@ -1751,7 +1667,7 @@ public class Graph { stopContPart.add(currentLoop.loopContinue); GraphPart precoBackup = currentLoop.loopPreContinue; currentLoop.loopPreContinue = null; - loopItem.commands.addAll(printGraph(visited, localData, new TranslateStack(), allParts, null, precoBackup, stopContPart, loops, null, staticOperation, path, recursionLevel + 1)); + loopItem.commands.addAll(printGraph(visited, localData, new TranslateStack(path), allParts, null, precoBackup, stopContPart, loops, null, staticOperation, path, recursionLevel + 1)); } } @@ -1788,7 +1704,7 @@ public class Graph { GraphTargetItem expr = ifi.expression; if (inverted) { if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); + expr = ((LogicalOpItem) expr).invert(null); } else { expr = new NotItem(null, expr); } @@ -1808,7 +1724,7 @@ public class Graph { currentLoop.loopPreContinue = null; List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(currentLoop.loopContinue); - finalComm = printGraph(visited, localData, new TranslateStack(), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + finalComm = printGraph(visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); currentLoop.loopPreContinue = backup; checkContinueAtTheEnd(finalComm, currentLoop); } @@ -1848,11 +1764,7 @@ public class Graph { List exprList = new ArrayList<>(); GraphTargetItem expr = ifi.expression; if (inverted) { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } + expr = expr.invert(null); } checkContinueAtTheEnd(bodyBranch, currentLoop); @@ -1889,7 +1801,7 @@ public class Graph { currentLoop.loopPreContinue = null; List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(currentLoop.loopContinue); - List finalComm = printGraph(visited, localData, new TranslateStack(), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + List finalComm = printGraph(visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); currentLoop.loopPreContinue = backup; checkContinueAtTheEnd(finalComm, currentLoop); @@ -1914,11 +1826,7 @@ public class Graph { List exprList = new ArrayList<>(finalComm); GraphTargetItem expr = ifi.expression; if (invert) { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } + expr = expr.invert(null); } exprList.add(expr); ret.add(index, li = new DoWhileItem(null, currentLoop, loopItem.commands, exprList)); @@ -1943,7 +1851,7 @@ public class Graph { } if (currentLoop.loopBreak != null) { - ret.addAll(printGraph(visited, localData, stack, allParts, part, currentLoop.loopBreak, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); + ret.addAll(printGraph(visited, localData, sPreLoop, allParts, part, currentLoop.loopBreak, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); } } @@ -2157,4 +2065,35 @@ public class Graph { } while (part != null); return ret; } + + protected static void makeAllStack(List commands, TranslateStack stack) { + int pcnt = 0; + for (int i = commands.size() - 1; i >= 0; i--) { + if (commands.get(i) instanceof PushItem) { + pcnt++; + } else { + break; + } + } + for (int i = commands.size() - pcnt; i < commands.size(); i++) { + stack.push(commands.remove(i).value); + i--; + } + } + + protected static void makeAllCommands(List commands, TranslateStack stack) { + int clen = commands.size(); + BreakItem br = null; + if (!commands.isEmpty()) { + if (commands.get(commands.size() - 1) instanceof BreakItem) { + clen--; + } + } + while (stack.size() > 0) { + GraphTargetItem p = stack.pop(); + if (!(p instanceof PopItem)) { + commands.add(clen, new PushItem(p)); + } + } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java index 2e4e823b4..39c25a6a6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java @@ -1,52 +1,52 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.graph; - -import com.jpexs.decompiler.flash.BaseLocalData; -import java.io.Serializable; -import java.util.List; - -/** - * - * @author JPEXS - */ -public interface GraphSourceItem extends Serializable { - - public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException; - - public boolean isJump(); - - public boolean isBranch(); - - public boolean isExit(); - - public long getOffset(); - - public boolean ignoredLoops(); - - public List getBranches(GraphSource code); - - public boolean isIgnored(); - - public void setIgnored(boolean ignored, int pos); - - public boolean isDeobfuscatePop(); - - public int getLine(); - - public String getFile(); -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph; + +import com.jpexs.decompiler.flash.BaseLocalData; +import java.io.Serializable; +import java.util.List; + +/** + * + * @author JPEXS + */ +public interface GraphSourceItem extends Serializable, Cloneable { + + public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException; + + public boolean isJump(); + + public boolean isBranch(); + + public boolean isExit(); + + public long getOffset(); + + public boolean ignoredLoops(); + + public List getBranches(GraphSource code); + + public boolean isIgnored(); + + public void setIgnored(boolean ignored, int pos); + + public boolean isDeobfuscatePop(); + + public int getLine(); + + public String getFile(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index 8ccf9786e..34318ea16 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -1,298 +1,319 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.graph; - -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; -import com.jpexs.decompiler.graph.model.BinaryOp; -import com.jpexs.decompiler.graph.model.LocalData; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * - * @author JPEXS - */ -public abstract class GraphTargetItem implements Serializable { - - public static final int PRECEDENCE_PRIMARY = 0; - - public static final int PRECEDENCE_POSTFIX = 1; - - public static final int PRECEDENCE_UNARY = 2; - - public static final int PRECEDENCE_MULTIPLICATIVE = 3; - - public static final int PRECEDENCE_ADDITIVE = 4; - - public static final int PRECEDENCE_BITWISESHIFT = 5; - - public static final int PRECEDENCE_RELATIONAL = 6; - - public static final int PRECEDENCE_EQUALITY = 7; - - public static final int PRECEDENCE_BITWISEAND = 8; - - public static final int PRECEDENCE_BITWISEXOR = 9; - - public static final int PRECEDENCE_BITWISEOR = 10; - - public static final int PRECEDENCE_LOGICALAND = 11; - - public static final int PRECEDENCE_LOGICALOR = 12; - - public static final int PRECEDENCE_CONDITIONAL = 13; - - public static final int PRECEDENCE_ASSIGMENT = 14; - - public static final int PRECEDENCE_COMMA = 15; - - public static final int NOPRECEDENCE = 16; - - public GraphSourceItem src; - - public int pos = -1; - - protected int precedence; - - public List moreSrc = new ArrayList<>(); - - public GraphPart firstPart; - - public GraphTargetItem value; - - protected HighlightData srcData = new HighlightData(); - - public int getLine() { - if (src != null) { - return src.getLine(); - } - return 0; - } - - public String getFile() { - if (src != null) { - return src.getFile(); - } - return null; - } - - public GraphPart getFirstPart() { - if (value == null) { - return firstPart; - } - GraphPart ret = value.getFirstPart(); - if (ret == null) { - return firstPart; - } - return ret; - } - - public GraphTargetItem() { - this(null, NOPRECEDENCE); - } - - public GraphTargetItem(GraphSourceItem src, int precedence) { - this.src = src; - this.precedence = precedence; - } - - public List getNeededSources() { - List ret = new ArrayList<>(); - ret.add(new GraphSourceItemPos(src, pos)); - ret.addAll(moreSrc); - if (value != null) { - ret.addAll(value.getNeededSources()); - } - return ret; - } - - public GraphTextWriter toStringSemicoloned(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.startOffset(src, pos, srcData); - appendTo(writer, localData); - if (needsSemicolon()) { - writer.appendNoHilight(";"); - } - writer.endOffset(); - return writer; - } - - public boolean needsSemicolon() { - return true; - } - - @Override - public String toString() { - return this.getClass().getName(); - } - - public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.startOffset(src, pos, srcData); - appendTo(writer, localData); - writer.endOffset(); - return writer; - } - - public abstract GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException; - - public String toString(LocalData localData) throws InterruptedException { - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - toString(writer, localData); - return writer.toString(); - } - - public int getPrecedence() { - return precedence; - } - - public boolean isCompileTime() { - Set dependencies = new HashSet<>(); - dependencies.add(this); - return isCompileTime(dependencies); - } - - public boolean isCompileTime(Set dependencies) { - return false; - } - - public boolean hasSideEffect() { - return false; - } - - public boolean isVariableComputed() { - return false; - } - - public Object getResult() { - return null; - } - - public String toStringNoQuotes(LocalData localData) { - return toString(); - } - - public GraphTextWriter toStringNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.startOffset(src, pos, srcData); - appendToNoQuotes(writer, localData); - writer.endOffset(); - return writer; - } - - public GraphTextWriter appendToNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return toString(writer, localData); - } - - public GraphTargetItem getNotCoerced() { - return this; - } - - public GraphTargetItem getThroughRegister() { - return this; - } - - public boolean needsNewLine() { - return false; - } - - public GraphTextWriter toStringNL(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.startOffset(src, pos, srcData); - appendTo(writer, localData); - if (needsNewLine()) { - writer.newLine(); - } - writer.endOffset(); - return writer; - } - - public boolean isEmpty() { - return false; - } - - public GraphTargetItem getThroughNotCompilable() { - return this; - } - - public GraphTargetItem getThroughDuplicate() { - return this; - } - - public boolean valueEquals(GraphTargetItem target) { - return equals(target); - } - - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - return new ArrayList<>(); - } - - public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - if (!hasReturnValue()) { - return toSource(localData, generator); - } - return generator.generateDiscardValue(localData, this); - } - - protected List toSourceBinary(BinaryOp op, GraphSourceItem action) { - List ret = new ArrayList<>(); - - return ret; - } - - public static List toSourceMerge(SourceGeneratorLocalData localData, SourceGenerator gen, Object... tar) throws CompilationException { - List ret = new ArrayList<>(); - for (Object o : tar) { - if (o == null) { - continue; - } - if (o instanceof GraphTargetItem) { - ret.addAll(((GraphTargetItem) o).toSource(localData, gen)); - } - if (o instanceof GraphSourceItem) { - ret.add((GraphSourceItem) o); - } - if (o instanceof List) { - List l = (List) o; - for (Object o2 : l) { - if (o2 instanceof GraphSourceItem) { - ret.add((GraphSourceItem) o2); - } - if (o2 instanceof GraphTargetItem) { - ret.addAll(((GraphTargetItem) o2).toSource(localData, gen)); - } - } - } - } - return ret; - } - - public abstract boolean hasReturnValue(); - - public List getAllSubItems() { - List ret = new ArrayList<>(); - if (value != null) { - ret.add(value); - } - return ret; - } - - public abstract GraphTargetItem returnType(); -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; +import com.jpexs.decompiler.graph.model.BinaryOp; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.decompiler.graph.model.LogicalOpItem; +import com.jpexs.decompiler.graph.model.NotItem; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public abstract class GraphTargetItem implements Serializable, Cloneable { + + public static final int PRECEDENCE_PRIMARY = 0; + + public static final int PRECEDENCE_POSTFIX = 1; + + public static final int PRECEDENCE_UNARY = 2; + + public static final int PRECEDENCE_MULTIPLICATIVE = 3; + + public static final int PRECEDENCE_ADDITIVE = 4; + + public static final int PRECEDENCE_BITWISESHIFT = 5; + + public static final int PRECEDENCE_RELATIONAL = 6; + + public static final int PRECEDENCE_EQUALITY = 7; + + public static final int PRECEDENCE_BITWISEAND = 8; + + public static final int PRECEDENCE_BITWISEXOR = 9; + + public static final int PRECEDENCE_BITWISEOR = 10; + + public static final int PRECEDENCE_LOGICALAND = 11; + + public static final int PRECEDENCE_LOGICALOR = 12; + + public static final int PRECEDENCE_CONDITIONAL = 13; + + public static final int PRECEDENCE_ASSIGMENT = 14; + + public static final int PRECEDENCE_COMMA = 15; + + public static final int NOPRECEDENCE = 16; + + public GraphSourceItem src; + + public int pos = -1; + + protected int precedence; + + public List moreSrc = new ArrayList<>(); + + public GraphPart firstPart; + + public GraphTargetItem value; + + protected HighlightData srcData = new HighlightData(); + + public int getLine() { + if (src != null) { + return src.getLine(); + } + return 0; + } + + public String getFile() { + if (src != null) { + return src.getFile(); + } + return null; + } + + public GraphPart getFirstPart() { + if (value == null) { + return firstPart; + } + GraphPart ret = value.getFirstPart(); + if (ret == null) { + return firstPart; + } + return ret; + } + + public GraphTargetItem() { + this(null, NOPRECEDENCE); + } + + public GraphTargetItem(GraphSourceItem src, int precedence) { + this.src = src; + this.precedence = precedence; + } + + public List getNeededSources() { + List ret = new ArrayList<>(); + ret.add(new GraphSourceItemPos(src, pos)); + ret.addAll(moreSrc); + if (value != null) { + ret.addAll(value.getNeededSources()); + } + return ret; + } + + public GraphTextWriter toStringSemicoloned(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startOffset(src, pos, srcData); + appendTo(writer, localData); + if (needsSemicolon()) { + writer.appendNoHilight(";"); + } + writer.endOffset(); + return writer; + } + + public boolean needsSemicolon() { + return true; + } + + @Override + public String toString() { + return this.getClass().getName(); + } + + public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startOffset(src, pos, srcData); + appendTo(writer, localData); + writer.endOffset(); + return writer; + } + + public abstract GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException; + + public String toString(LocalData localData) throws InterruptedException { + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); + toString(writer, localData); + return writer.toString(); + } + + public int getPrecedence() { + return precedence; + } + + public boolean isCompileTime() { + Set dependencies = new HashSet<>(); + dependencies.add(this); + return isCompileTime(dependencies); + } + + public boolean isCompileTime(Set dependencies) { + return false; + } + + public boolean hasSideEffect() { + return false; + } + + public boolean isVariableComputed() { + return false; + } + + public Object getResult() { + return null; + } + + public String toStringNoQuotes(LocalData localData) { + return toString(); + } + + public GraphTextWriter toStringNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startOffset(src, pos, srcData); + appendToNoQuotes(writer, localData); + writer.endOffset(); + return writer; + } + + public GraphTextWriter appendToNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { + return toString(writer, localData); + } + + public GraphTargetItem getNotCoerced() { + return this; + } + + public GraphTargetItem getThroughRegister() { + return this; + } + + public boolean needsNewLine() { + return false; + } + + public GraphTextWriter toStringNL(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startOffset(src, pos, srcData); + appendTo(writer, localData); + if (needsNewLine()) { + writer.newLine(); + } + writer.endOffset(); + return writer; + } + + public boolean isEmpty() { + return false; + } + + public GraphTargetItem getThroughNotCompilable() { + return this; + } + + public GraphTargetItem getThroughDuplicate() { + return this; + } + + public boolean valueEquals(GraphTargetItem target) { + return equals(target); + } + + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return new ArrayList<>(); + } + + public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + if (!hasReturnValue()) { + return toSource(localData, generator); + } + return generator.generateDiscardValue(localData, this); + } + + protected List toSourceBinary(BinaryOp op, GraphSourceItem action) { + List ret = new ArrayList<>(); + + return ret; + } + + public static List toSourceMerge(SourceGeneratorLocalData localData, SourceGenerator gen, Object... tar) throws CompilationException { + List ret = new ArrayList<>(); + for (Object o : tar) { + if (o == null) { + continue; + } + if (o instanceof GraphTargetItem) { + ret.addAll(((GraphTargetItem) o).toSource(localData, gen)); + } + if (o instanceof GraphSourceItem) { + ret.add((GraphSourceItem) o); + } + if (o instanceof List) { + List l = (List) o; + for (Object o2 : l) { + if (o2 instanceof GraphSourceItem) { + ret.add((GraphSourceItem) o2); + } + if (o2 instanceof GraphTargetItem) { + ret.addAll(((GraphTargetItem) o2).toSource(localData, gen)); + } + } + } + } + return ret; + } + + public abstract boolean hasReturnValue(); + + public List getAllSubItems() { + List ret = new ArrayList<>(); + if (value != null) { + ret.add(value); + } + return ret; + } + + public abstract GraphTargetItem returnType(); + + @Override + protected GraphTargetItem clone() { + try { + return (GraphTargetItem) super.clone(); + } catch (CloneNotSupportedException ex) { + return null; + } + } + + /*public GraphTargetItem invert() { + return invert(null); + }*/ + public GraphTargetItem invert(GraphSourceItem src) { + return new NotItem(src, this); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java new file mode 100644 index 000000000..e9bd81880 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java @@ -0,0 +1,10 @@ +package com.jpexs.decompiler.graph; + +/** + * + * @author JPEXS + */ +public interface SimpleValue { + + public boolean isSimpleValue(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java index 7c1694d78..0eb8d34b3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -22,12 +23,14 @@ import com.jpexs.decompiler.graph.model.CommaExpressionItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.DoWhileItem; import com.jpexs.decompiler.graph.model.DuplicateItem; +import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.ForItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; +import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.decompiler.graph.model.WhileItem; import java.util.List; @@ -37,6 +40,10 @@ import java.util.List; */ public interface SourceGenerator { + public List generate(SourceGeneratorLocalData localData, TrueItem item) throws CompilationException; + + public List generate(SourceGeneratorLocalData localData, FalseItem item) throws CompilationException; + public List generate(SourceGeneratorLocalData localData, AndItem item) throws CompilationException; public List generate(SourceGeneratorLocalData localData, OrItem item) throws CompilationException; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java index 647519182..cc68f15ea 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java @@ -16,11 +16,51 @@ */ package com.jpexs.decompiler.graph; +import com.jpexs.decompiler.graph.model.PopItem; import java.util.Stack; +import java.util.logging.Level; +import java.util.logging.Logger; /** * * @author JPEXS */ public class TranslateStack extends Stack { + + private static PopItem pop = new PopItem(null); + + private String path; + + public TranslateStack(String path) { + this.path = path; + } + + public String getPath() { + return path; + } + + @Override + public synchronized GraphTargetItem peek() { + if (path != null) { + if (this.isEmpty()) { + Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attemp to Peek empty stack", path); + return pop; + } + } + return super.peek(); + } + + @Override + public synchronized GraphTargetItem pop() { + if (path != null) { + if (this.isEmpty()) { + PopItem oldpop = pop; + pop = new PopItem(null); + Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attemp to Pop empty stack", path); + return oldpop; + } + } + return super.pop(); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java index c1f8f8f87..3e655bdf3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -20,6 +21,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import java.util.List; @@ -29,7 +31,7 @@ import java.util.Set; * * @author JPEXS */ -public class DuplicateItem extends GraphTargetItem { +public class DuplicateItem extends GraphTargetItem implements SimpleValue { public DuplicateItem(GraphSourceItem src, GraphTargetItem value) { super(src, value.getPrecedence()); @@ -43,7 +45,12 @@ public class DuplicateItem extends GraphTargetItem { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return value.toString(writer, localData); + if ((value instanceof SimpleValue) && (((SimpleValue) value).isSimpleValue())) { + return value.appendTo(writer, localData); + } + writer.append("§§dup("); + value.appendTo(writer, localData); + return writer.append(")"); } @Override @@ -89,4 +96,14 @@ public class DuplicateItem extends GraphTargetItem { public GraphTargetItem returnType() { return TypeItem.UNBOUNDED; } + + /*@Override + public GraphTargetItem invert(GraphSourceItem src) { + return //new DuplicateItem(src, value instanceof NotItem ? (value.value) : new NotItem(src, value)); + }*/ + @Override + public boolean isSimpleValue() { + return ((value instanceof SimpleValue) && ((SimpleValue) value).isSimpleValue()); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ExitItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ExitItem.java index b02e93c69..b1a6fefe6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ExitItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ExitItem.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java new file mode 100644 index 000000000..f9704f06f --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. */ +package com.jpexs.decompiler.graph.model; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.TypeItem; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class FalseItem extends GraphTargetItem implements LogicalOpItem, SimpleValue { + + public FalseItem(GraphSourceItem src) { + super(src, PRECEDENCE_PRIMARY); + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) { + return writer.append("false"); + } + + @Override + public boolean hasReturnValue() { + return true; + } + + @Override + public GraphTargetItem returnType() { + return TypeItem.BOOLEAN; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return generator.generate(localData, this); + } + + @Override + public GraphTargetItem invert(GraphSourceItem neqSrc) { + return new TrueItem(null); + } + + @Override + public boolean isSimpleValue() { + return true; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java index c3bd312ca..43f9f7caf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java @@ -75,11 +75,7 @@ public class IfItem extends GraphTargetItem implements Block { expr = ((NotItem) expr).getOriginal(); } } else { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } + expr = expr.invert(null); ifBranch = onFalse; elseBranch = onTrue; } @@ -112,7 +108,10 @@ public class IfItem extends GraphTargetItem implements Block { } for (GraphTargetItem ti : elseBranch) { if (!ti.isEmpty()) { - ti.toStringSemicoloned(writer, localData).newLine(); + ti.toStringSemicoloned(writer, localData); + if (!elseIf) { + writer.newLine(); + } } } if (!elseIf) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LogicalOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LogicalOpItem.java index 3cfd1eaad..de055b908 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LogicalOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LogicalOpItem.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; +import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; /** @@ -23,5 +25,5 @@ import com.jpexs.decompiler.graph.GraphTargetItem; */ public interface LogicalOpItem { - public GraphTargetItem invert(); + public GraphTargetItem invert(GraphSourceItem src); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java index a7369764f..5becbe13e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -57,11 +58,6 @@ public class NotItem extends UnaryOpItem implements LogicalOpItem, Inverted { return value.isCompileTime(dependencies); } - @Override - public GraphTargetItem invert() { - return value; - } - public GraphTargetItem getOriginal() { return value; } @@ -80,4 +76,10 @@ public class NotItem extends UnaryOpItem implements LogicalOpItem, Inverted { public GraphTargetItem returnType() { return TypeItem.BOOLEAN; } + + @Override + public GraphTargetItem invert(GraphSourceItem src) { + return value; + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PopItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PopItem.java new file mode 100644 index 000000000..68ed404f5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PopItem.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph.model; + +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TypeItem; + +/** + * + * @author JPEXS + */ +public class PopItem extends GraphTargetItem { + + public PopItem(GraphSourceItem src) { + super(src, PRECEDENCE_PRIMARY); + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + //Logger.getLogger(PopItem.class.getName()).log(Level.WARNING, "Pop item left in the source code"); + writer.append("§§pop()"); + return writer; + } + + @Override + public boolean hasReturnValue() { + return true; + } + + @Override + public GraphTargetItem returnType() { + return TypeItem.UNBOUNDED; + } + + @Override + public Object getResult() { + return new Null(); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PushItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PushItem.java new file mode 100644 index 000000000..a26566786 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PushItem.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph.model; + +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.GraphTargetItem; + +/** + * + * @author JPEXS + */ +public class PushItem extends GraphTargetItem { + + public PushItem(GraphTargetItem val) { + super(val.src, val.getPrecedence()); + this.value = val; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + //Logger.getLogger(PushItem.class.getName()).log(Level.WARNING, "Push item left in the source code"); + writer.append("§§push("); + value.appendTo(writer, localData); + writer.append(")"); + return writer; + } + + @Override + public boolean hasReturnValue() { + return true; + } + + @Override + public GraphTargetItem returnType() { + return value.returnType(); + } + + @Override + public GraphTargetItem getNotCoerced() { + return value.getNotCoerced(); + } + + @Override + public GraphTargetItem getThroughDuplicate() { + return value.getThroughDuplicate(); + } + + @Override + public GraphTargetItem getThroughRegister() { + return value.getThroughRegister(); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java index 07ebbbd62..99069a463 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java @@ -1,30 +1,36 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; +import java.util.List; /** * * @author JPEXS */ -public class TrueItem extends GraphTargetItem { +public class TrueItem extends GraphTargetItem implements LogicalOpItem, SimpleValue { public TrueItem(GraphSourceItem src) { super(src, PRECEDENCE_PRIMARY); @@ -44,4 +50,19 @@ public class TrueItem extends GraphTargetItem { public GraphTargetItem returnType() { return TypeItem.BOOLEAN; } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return generator.generate(localData, this); + } + + @Override + public GraphTargetItem invert(GraphSourceItem neqSrc) { + return new FalseItem(null); + } + + @Override + public boolean isSimpleValue() { + return true; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java index 9c4d3f434..d9fa93719 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java @@ -25,8 +25,6 @@ import java.util.Set; public abstract class UnaryOpItem extends GraphTargetItem implements UnaryOp { - public GraphTargetItem value; - public String operator; public UnaryOpItem(GraphSourceItem instruction, int precedence, GraphTargetItem value, String operator) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java index 2d4d117ff..afe5c4f7b 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java @@ -1,806 +1,807 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.helpers.CodeFormatting; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.tags.DoActionTag; -import com.jpexs.decompiler.flash.tags.ShowFrameTag; -import com.jpexs.decompiler.flash.tags.Tag; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -/** - * - * @author JPEXS - */ -public class ActionScript2Test extends ActionStript2TestBase { - - @BeforeClass - public void init() throws IOException, InterruptedException { - //Main.initLogging(false); - Configuration.autoDeobfuscate.set(false); - Configuration.decompile.set(true); - Configuration.registerNameFormat.set("_loc%d_"); - swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false); - } - - private void compareSrc(int frame, String expectedResult) { - DoActionTag doa = getFrameSource(frame); - assertNotNull(doa); - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - try { - Action.actionsToSource(doa, doa.getActions(), "", writer); - } catch (InterruptedException ex) { - fail(); - } - String actualResult = cleanPCode(writer.toString()); - expectedResult = cleanPCode(expectedResult); - assertEquals(actualResult, expectedResult); - - } - - private DoActionTag getFrameSource(int frame) { - int f = 0; - DoActionTag lastDoa = null; - - for (Tag t : swf.tags) { - if (t instanceof DoActionTag) { - lastDoa = (DoActionTag) t; - } - if (t instanceof ShowFrameTag) { - f++; - if (f == frame) { - return lastDoa; - } - lastDoa = null; - } - } - return null; - } - - @Test - public void frame23_Test() { - compareSrc(23, "stop();\r\n" - ); - } - - @Test - public void frame24_unicodeTest() { - compareSrc(24, "trace(\"unicodeTest\");\r\n" - + "var k = \"\u05d4\u05d9\u05e4\u05d5\u05e4\u05d5\u05d8\u05de\u05d9, \u05d0\u05d5 \u05d0\";\r\n" - + "trace(k);\r\n" - ); - } - - @Test - public void frame25_ifWithElseTest() { - compareSrc(25, "trace(\"ifWithElseTest\");\r\n" - + "var i = 5;\r\n" - + "if(i == 258)\r\n" - + "{\r\n" - + "trace(\"onTrue\");\r\n" - + "}\r\n" - + "else\r\n" - + "{\r\n" - + "trace(\"onFalse\" + i);\r\n" - + "}\r\n" - ); - } - - @Test - public void frame26_forTest() { - compareSrc(26, "trace(\"forTest\");\r\n" - + "var i = 0;\r\n" - + "while(i < 10)\r\n" - + "{\r\n" - + "trace(\"hello:\" + i);\r\n" - + "i++;\r\n" - + "}\r\n" - ); - } - - @Test - public void frame27_whileTest() { - compareSrc(27, "trace(\"whileTest\");\r\n" - + "var i = 0;\r\n" - + "while(i < 10)\r\n" - + "{\r\n" - + "trace(\"hello:\" + i);\r\n" - + "i++;\r\n" - + "}\r\n" - ); - } - - @Test - public void frame28_forWithContinueTest() { - compareSrc(28, "trace(\"forWithContinueTest\");\r\n" - + "var i = 0;\r\n" - + "for(; i < 10; i++)\r\n" - + "{\r\n" - + "trace(\"hello:\" + i);\r\n" - + "if(i == 5)\r\n" - + "{\r\n" - + "trace(\"i==5\");\r\n" - + "if(i == 7)\r\n" - + "{\r\n" - + "continue;\r\n" - + "}\r\n" - + "trace(\"hawk\");\r\n" - + "}\r\n" - + "trace(\"end of the loop\");\r\n" - + "}\r\n" - ); - } - - @Test - public void frame29_doWhileTest() { - compareSrc(29, "trace(\"doWhileTest\");\r\n" - + "var i = 0;\r\n" - + "do\r\n" - + "{\r\n" - + "trace(\"i=\" + i);\r\n" - + "i++;\r\n" - + "}\r\n" - + "while(i < 10);\r\n" - + "trace(\"end\");\r\n" - ); - } - - @Test - public void frame30_switchTest() { - compareSrc(30, "trace(\"switchTest\");\r\n" - + "var i = 5;\r\n" - + "switch(i)\r\n" - + "{\r\n" - + "case 0:\r\n" - + "case 1:\r\n" - + "trace(\"one\");\r\n" - + "break;\r\n" - + "case 2:\r\n" - + "trace(\"two\");\r\n" - + "case 3:\r\n" - + "trace(\"three\");\r\n" - + "break;\r\n" - + "case 4:\r\n" - + "trace(\"four\");\r\n" - + "break;\r\n" - + "default:\r\n" - + "trace(\"default clause\");\r\n" - + "}\r\n" - + "trace(\"scriptend\");\r\n" - ); - } - - @Test - public void frame31_strictEqualsTest() { - compareSrc(31, "trace(\"strictEqualsTest\");\r\n" - + "var i = 5;\r\n" - + "if(i === 5)\r\n" - + "{\r\n" - + "trace(\"equals strict\");\r\n" - + "}\r\n" - + "if(!(i === 5))\r\n" - + "{\r\n" - + "trace(\"not equals strict\");\r\n" - + "}\r\n" - ); - } - - @Test - public void frame32_switchForTest() { - compareSrc(32, "trace(\"switchForTest\");\r\n" - + "var i = 0;\r\n" - + "for(; i < 10; i++)\r\n" - + "{\r\n" - + "switch(i)\r\n" - + "{\r\n" - + "case 0:\r\n" - + "trace(\"zero\");\r\n" - + "continue;\r\n" - + "case 5:\r\n" - + "trace(\"five\");\r\n" - + "break;\r\n" - + "case 10:\r\n" - + "trace(\"ten\");\r\n" - + "break;\r\n" - + "case 1:\r\n" - + "if(i == 7)\r\n" - + "{\r\n" - + "continue;\r\n" - + "}\r\n" - + "trace(\"one\");\r\n" - + "default:\r\n" - + "trace(\"def\");\r\n" - + "}\r\n" - + "trace(\"before loop end\");\r\n" - + "}\r\n" - ); - } - - @Test - public void frame33_functionTest() { - compareSrc(33, "function hello(what, second)\r\n" - + "{\r\n" - + "trace(\"hello \" + what + \"! \" + second);\r\n" - + "}\r\n" - + "trace(\"functionTest\");\r\n" - + "hello(\"friend\",7);\r\n" - ); - } - - @Test - public void frame34_multipleConditionsTest() { - compareSrc(34, "trace(\"multipleConditionsTest\");\r\n" - + "var k = 5;\r\n" - + "if(k == 7 && k == 8)\r\n" - + "{\r\n" - + "trace(\"first\");\r\n" - + "}\r\n" - + "if(k == 9)\r\n" - + "{\r\n" - + "trace(\"second\");\r\n" - + "}\r\n" - + "trace(\"finish\");\r\n" - ); - } - - @Test - public void frame35_multipleConditions2Test() { - compareSrc(35, "trace(\"multipleConditions2Test\");\r\n" - + "var k = 5;\r\n" - + "if(k == 7 && k == 8)\r\n" - + "{\r\n" - + "trace(\"first\");\r\n" - + "}\r\n" - + "if(k == 9 || k == 6)\r\n" - + "{\r\n" - + "trace(\"second\");\r\n" - + "}\r\n" - + "trace(\"finish\");\r\n" - ); - } - - @Test - public void frame36_chainedAssignmentsTest() { - compareSrc(36, "trace(\"chainedAssignmentsTest\");\r\n" - + "var a = 7;\r\n" - + "var b = 8;\r\n" - + "var c = 9;\r\n" - + "var d = c = b = a = 10;\r\n" - + "trace(d);\r\n" - ); - } - - @Test - public void frame37_objectsTest() { - compareSrc(37, "trace(\"objectsTest\");\r\n" - + "var flashBox = new Box(box1);\r\n" - + "_root.onEnterFrame = function()\r\n" - + "{\r\n" - + "flashBox.moveUp();\r\n" - + "};\r\n" - + "var ship = new Ship(200);\r\n" - + "var enemy = new Enemy(56);\r\n" - + "ship.moveDown(0.5);\r\n" - + "ship.moveUp(0.2);\r\n" - + "enemy.moveRight(230);\r\n" - + "enemy.moveLeft(100);\r\n" - + "var mt = new com.jpexs.MyTest();\r\n" - + "mt.test();\r\n" - + "var c = new Cox(box1);\r\n" - ); - } - - @Test - public void frame38_doWhile2Test() { - compareSrc(38, "trace(\"doWhile2Test\");\r\n" - + "var k = 5;\r\n" - + "do\r\n" - + "{\r\n" - + "k++;\r\n" - + "if(k == 7)\r\n" - + "{\r\n" - + "k = 5 * k;\r\n" - + "}\r\n" - + "else\r\n" - + "{\r\n" - + "k = 5 + k;\r\n" - + "}\r\n" - + "}\r\n" - + "while(k < 9);\r\n" - ); - } - - @Test - public void frame39_whileAndTest() { - compareSrc(39, "trace(\"whileAndTest\");\r\n" - + "var a = 5;\r\n" - + "var b = 10;\r\n" - + "while(a < 10 && b > 1)\r\n" - + "{\r\n" - + "a++;\r\n" - + "b--;\r\n" - + "}\r\n" - + "a = 7;\r\n" - + "b = 9;\r\n" - ); - } - - @Test - public void frame40_forInTest() { - compareSrc(40, "function testForIn()\r\n" - + "{\r\n" - + "var _loc1_ = [];\r\n" - + "for(var _loc2_ in _loc1_)\r\n" - + "{\r\n" - + "if(_loc2_ > 3)\r\n" - + "{\r\n" - + "if(_loc2_ == 5)\r\n" - + "{\r\n" - + "return 7;\r\n" - + "}\r\n" - + "return 8;\r\n" - + "}\r\n" - + "}\r\n" - + "}\r\n" - + "trace(\"forInTest\");\r\n" - + "trace(testForIn());\r\n" - + "var arr = [];\r\n" - + "for(var a in arr)\r\n" - + "{\r\n" - + "trace(a);\r\n" - + "}\r\n" - ); - } - - @Test - public void frame41_tryTest() { - compareSrc(41, "trace(\"tryTest\");\r\n" - + "var k = 5;\r\n" - + "try\r\n" - + "{\r\n" - + "k = Infinity;\r\n" - + "}\r\n" - + "catch(e)\r\n" - + "{\r\n" - + "trace(\"bug \" + e);\r\n" - + "}\r\n" - + "finally\r\n" - + "{\r\n" - + "trace(\"huu\");\r\n" - + "}\r\n" - + "trace(\"next\");\r\n" - + "try\r\n" - + "{\r\n" - + "k = 6;\r\n" - + "}\r\n" - + "catch(e)\r\n" - + "{\r\n" - + "trace(\"bug2 \" + e);\r\n" - + "}\r\n" - + "trace(\"next2\");\r\n" - + "var k = 5;\r\n" - + "try\r\n" - + "{\r\n" - + "k = Infinity;\r\n" - + "}\r\n" - + "finally\r\n" - + "{\r\n" - + "trace(\"final\");\r\n" - + "}\r\n" - + "trace(\"end\");\r\n" - ); - } - - @Test - public void frame42_indicesTest() { - compareSrc(42, "trace(\"indicesTest\");\r\n" - + "var k = [1,2,3];\r\n" - + "var b = k[1];\r\n" - + "trace(b);\r\n" - ); - } - - @Test - public void frame43_incDecTest() { - compareSrc(43, "function tst()\r\n" - + "{\r\n" - + "return 1;\r\n" - + "}\r\n" - + "trace(\"incDecTest\");\r\n" - + "var i = 5;\r\n" - + "var b = i++;\r\n" - + "var c = --i + 5;\r\n" - + "trace(\"a:\" + a + \" b:\" + b + \" c:\" + c);\r\n" - + "var arr = [1,2,3];\r\n" - + "arr[tst()]++;\r\n" - + "var d = arr[tst()];\r\n" - + "trace(d);\r\n" - ); - } - - @Test - public void frame44_chainedAssignments2Test() { - compareSrc(44, "trace(\"chainedAssignments2Test\");\r\n" - + "var a = 5;\r\n" - + "var b = 6;\r\n" - + "var c = 7;\r\n" - + "var d = c = b = a = 4;\r\n" - + "if((d = c = b = a = 7) > 2)\r\n" - + "{\r\n" - + "trace(d);\r\n" - + "}\r\n" - + "trace(d + 1);\r\n" - + "var i = 0;\r\n" - + "while(i < 5)\r\n" - + "{\r\n" - + "if(i == 7)\r\n" - + "{\r\n" - + "}\r\n" - + "i++;\r\n" - + "}\r\n" - ); - } - - @Test - public void frame45_function2Test() { - compareSrc(45, "function a()\r\n" - + "{\r\n" - + "trace(\"hi\");\r\n" - + "var _loc1_ = 5;\r\n" - + "if(_loc1_ == 7)\r\n" - + "{\r\n" - + "return undefined;\r\n" - + "}\r\n" - + "_loc1_ = _loc1_ * 9;\r\n" - + "trace(_loc1_);\r\n" - + "}\r\n" - + "trace(\"function2Test\");\r\n" - ); - } - - @Test - public void frame46_tryFunctionTest() { - compareSrc(46, "function testtry()\r\n" - + "{\r\n" - + "var _loc1_ = 5;\r\n" - + "try\r\n" - + "{\r\n" - + "if(_loc1_ == 3)\r\n" - + "{\r\n" - + "return undefined;\r\n" - + "}\r\n" - + "if(_loc1_ == 4)\r\n" - + "{\r\n" - + "throw new Error();\r\n" - + "}\r\n" - + "else\r\n" - + "{\r\n" - + "_loc1_ = 7;\r\n" - + "}\r\n" - + "}\r\n" - + "catch(e)\r\n" - + "{\r\n" - + "trace(\"error\");\r\n" - + "}\r\n" - + "finally\r\n" - + "{\r\n" - + "trace(\"finally\");\r\n" - + "}\r\n" - + "}\r\n" - + "trace(\"tryFunctionTest\");\r\n" - ); - } - - @Test - public void frame47_ternarTest() { - compareSrc(47, "trace(\"ternarTest\");\r\n" - + "var a = 5;\r\n" - + "var b = a != 4?3:2;\r\n" - + "trace(b);\r\n" - ); - } - - @Test - public void frame48_forInInTest() { - compareSrc(48, "function tst()\r\n" - + "{\r\n" - + "var _loc2_ = [];\r\n" - + "_loc2_[0] = [];\r\n" - + "for(var _loc3_ in _loc2_)\r\n" - + "{\r\n" - + "for(var _loc1_ in _loc3_)\r\n" - + "{\r\n" - + "if(_loc1_ == 5)\r\n" - + "{\r\n" - + "return 5;\r\n" - + "}\r\n" - + "}\r\n" - + "if(_loc3_ == 8)\r\n" - + "{\r\n" - + "return 3;\r\n" - + "}\r\n" - + "}\r\n" - + "return 8;\r\n" - + "}\r\n" - + "trace(\"forInInTest\");\r\n" - + "tst();\r\n" - ); - } - - @Test - public void frame49_registersFuncTest() { - compareSrc(49, "function tst(px)\r\n" - + "{\r\n" - + "var _loc1_ = 57;\r\n" - + "_loc1_ = _loc1_ * 27;\r\n" - + "}\r\n" - + "trace(\"registersFuncTest\");\r\n" - + "tst(5);\r\n" - + "var s = String(5);\r\n" - ); - } - - @Test - public void frame50_ifFrameLoadedTest() { - compareSrc(50, "trace(\"ifFrameLoadedTest\");\r\n" - + "ifFrameLoaded(9)\r\n" - + "{\r\n" - + "trace(\"loaded\");\r\n" - + "}\r\n" - ); - } - - @Test - public void frame51_function3Test() { - compareSrc(51, "function tst()\r\n" - + "{\r\n" - + "var _loc1_ = 5;\r\n" - + "c = _loc1_ = 8;\r\n" - + "trace(\"hi\");\r\n" - + "trace(_loc1_);\r\n" - + "if((e = d = f = c = 9) > 5)\r\n" - + "{\r\n" - + "trace(\"dd\");\r\n" - + "}\r\n" - + "}\r\n" - + "trace(\"function3Test\");\r\n" - + "var c = 7;\r\n" - + "var d = 7;\r\n" - + "var e = 8;\r\n" - + "tst();\r\n" - ); - } - - @Test - public void frame52_commaOperatorTest() { - compareSrc(52, "trace(\"commaOperatorTest\");\r\n" - + "var a = 0;\r\n" - + "var b = 0;\r\n" - + "var c = 0;\r\n" - + "while(true)\r\n" - + "{\r\n" - + "a++;\r\n" - + "b = b + 2;\r\n" - + "if(c < 10)\r\n" - + "{\r\n" - + "trace(c);\r\n" - + "c++;\r\n" - + "continue;\r\n" - + "}\r\n" - + "break;\r\n" - + "}\r\n" - + "trace(\"konec\");\r\n" - ); - } - - @Test - public void frame53_commaOperator2Test() { - compareSrc(53, "trace(\"commaOperator2Test\");\r\n" - + "var k = 8;\r\n" - + "do\r\n" - + "{\r\n" - + "if(k == 9)\r\n" - + "{\r\n" - + "trace(\"h\");\r\n" - + "if(k == 9)\r\n" - + "{\r\n" - + "trace(\"f\");\r\n" - + "continue;\r\n" - + "}\r\n" - + "trace(\"b\");\r\n" - + "}\r\n" - + "trace(\"gg\");\r\n" - + "}\r\n" - + "while(k++, k < 10);\r\n" - + "trace(\"ss\");\r\n" - ); - } - - @Test - public void frame54_function4Test() { - compareSrc(54, "function tst()\r\n" - + "{\r\n" - + "var _loc1_ = 5;\r\n" - + "while(_loc1_ < 10)\r\n" - + "{\r\n" - + "if(_loc1_ == 5)\r\n" - + "{\r\n" - + "if(_loc1_ == 6)\r\n" - + "{\r\n" - + "return true;\r\n" - + "}\r\n" - + "_loc1_ = _loc1_ + 1;\r\n" - + "continue;\r\n" - + "}\r\n" - + "return false;\r\n" - + "}\r\n" - + "}\r\n" - + "trace(\"function4Test\");\r\n" - + "tst();\r\n" - ); - } - - @Test - public void frame55_pushTest() { - compareSrc(55, "trace(\"pushTest\");\r\n" - ); - } - - @Test - public void frame56_commaOperator3Test() { - compareSrc(56, "trace(\"commaOperator3Test\");\r\n" - + "var k = 1;\r\n" - + "while(true)\r\n" - + "{\r\n" - + "k++;\r\n" - + "if(k < 10)\r\n" - + "{\r\n" - + "k = k * 5;\r\n" - + "trace(k);\r\n" - + "continue;\r\n" - + "}\r\n" - + "break;\r\n" - + "}\r\n" - + "trace(\"end\");\r\n" - ); - } - - @Test - public void frame57_commaOperator4Test() { - compareSrc(57, "trace(\"commaOperator4Test\");\r\n" - + "var k = 0;\r\n" - + "do\r\n" - + "{\r\n" - + "trace(k);\r\n" - + "if(k == 8)\r\n" - + "{\r\n" - + "trace(\"a\");\r\n" - + "if(k == 9)\r\n" - + "{\r\n" - + "continue;\r\n" - + "}\r\n" - + "trace(\"d\");\r\n" - + "trace(\"b\");\r\n" - + "}\r\n" - + "k++;\r\n" - + "}\r\n" - + "while(k = k + 5, k < 20);\r\n" - + "trace(\"end\");\r\n" - ); - } - - @Test - public void frame58_globalFunctionsTest() { - compareSrc(58, "function tst(p1)\r\n" - + "{\r\n" - + "trace(\"test\");\r\n" - + "}\r\n" - + "trace(\"globalFunctionsTest\");\r\n" - + "var k = Array(1,2,3);\r\n" - + "var a = 1;\r\n" - + "var b = Boolean(a);\r\n" - + "call(5);\r\n" - + "var c = \"A\";\r\n" - + "clearInterval(5);\r\n" - + "clearTimeout(4);\r\n" - + "var mc;\r\n" - + "duplicateMovieClip(mc,\"copy\",16389);\r\n" - + "a = escape(\"how\");\r\n" - + "var f = a;\r\n" - + "fscommand(\"alert(\\\"hi\\\");\");\r\n" - + "a = mc._alpha;\r\n" - + "a = getTimer();\r\n" - + "getURL(\"http://localhost/\",\"wnd\",\"POST\");\r\n" - + "a = getVersion();\r\n" - + "gotoAndPlay(5);\r\n" - + "gotoAndStop(8);\r\n" - + "ifFrameLoaded(4)\r\n" - + "{\r\n" - + "trace(\"loaded\");\r\n" - + "}\r\n" - + "a = int(f);\r\n" - + "a = isFinite(f);\r\n" - + "a = isNaN(f);\r\n" - + "a = length(f);\r\n" - + "loadMovie(\"http://localhost/test.swf\",a,\"GET\");\r\n" - + "loadMovieNum(\"http://localhost/test.swf\",5,\"GET\");\r\n" - + "loadVariables(\"http://localhost/vars.txt\",a,\"GET\");\r\n" - + "loadVariablesNum(\"http://localhost/vars.txt\",4,\"GET\");\r\n" - + "a = mbchr(f);\r\n" - + "a = mblength(f);\r\n" - + "a = mbord(f);\r\n" - + "a = mbsubstring(\"aaaa\",5,4);\r\n" - + "MMExecute(\"destroyPC\");\r\n" - + "nextFrame();\r\n" - + "gotoAndStop(1);\r\n" - + "a = Number(f);\r\n" - + "a = Object(f);\r\n" - + "a = ord(f);\r\n" - + "a = parseFloat(f);\r\n" - + "a = parseInt(f,16);\r\n" - + "play();\r\n" - + "prevFrame();\r\n" - + "gotoAndStop(1);\r\n" - + "print(mc,\"bframe\");\r\n" - + "printAsBitmap(mc,\"bframe\");\r\n" - + "printAsBitmapNum(5,\"bframe\");\r\n" - + "printNum(4,\"bframe\");\r\n" - + "a = random(10);\r\n" - + "removeMovieClip(mc);\r\n" - + "setInterval(tst,5,f);\r\n" - + "mc._alpha = 25;\r\n" - + "setTimeout(tst,5,f);\r\n" - + "showRedrawRegions(false,0);\r\n" - + "startDrag(mc,1,5,5,6,6);\r\n" - + "stop();\r\n" - + "stopAllSounds();\r\n" - + "stopDrag();\r\n" - + "a = String(f);\r\n" - + "a = \"aa\";\r\n" - + "targetPath(f);\r\n" - + "tellTarget(mc)\r\n" - + "{\r\n" - + "trace(\"told\");\r\n" - + "}\r\n" - + "toggleHighQuality();\r\n" - + "a = unescape(f);\r\n" - + "unloadMovie(mc);\r\n" - + "unloadMovieNum(4);\r\n" - + "updateAfterEvent();\r\n" - ); - } - - @Test - public void frame59_unaryOpTest() { - compareSrc(59, "trace(\"unaryOpTest\");\r\n" - + "var a = 5;\r\n" - + "var c = ~a;\r\n" - + "var d = ~(a + c);\r\n" - + "var e = - c;\r\n" - ); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.tags.ShowFrameTag; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript2Test extends ActionStript2TestBase { + + @BeforeClass + public void init() throws IOException, InterruptedException { + //Main.initLogging(false); + Configuration.autoDeobfuscate.set(false); + Configuration.decompile.set(true); + Configuration.registerNameFormat.set("_loc%d_"); + swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false); + } + + private void compareSrc(int frame, String expectedResult) { + DoActionTag doa = getFrameSource(frame); + assertNotNull(doa); + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + try { + Action.actionsToSource(doa, doa.getActions(), "", writer); + } catch (InterruptedException ex) { + fail(); + } + String actualResult = cleanPCode(writer.toString()); + expectedResult = cleanPCode(expectedResult); + assertEquals(actualResult, expectedResult); + + } + + private DoActionTag getFrameSource(int frame) { + int f = 0; + DoActionTag lastDoa = null; + + for (Tag t : swf.tags) { + if (t instanceof DoActionTag) { + lastDoa = (DoActionTag) t; + } + if (t instanceof ShowFrameTag) { + f++; + if (f == frame) { + return lastDoa; + } + lastDoa = null; + } + } + return null; + } + + @Test + public void frame23_Test() { + compareSrc(23, "stop();\r\n" + ); + } + + @Test + public void frame24_unicodeTest() { + compareSrc(24, "trace(\"unicodeTest\");\r\n" + + "var k = \"\u05d4\u05d9\u05e4\u05d5\u05e4\u05d5\u05d8\u05de\u05d9, \u05d0\u05d5 \u05d0\";\r\n" + + "trace(k);\r\n" + ); + } + + @Test + public void frame25_ifWithElseTest() { + compareSrc(25, "trace(\"ifWithElseTest\");\r\n" + + "var i = 5;\r\n" + + "if(i == 258)\r\n" + + "{\r\n" + + "trace(\"onTrue\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"onFalse\" + i);\r\n" + + "}\r\n" + ); + } + + @Test + public void frame26_forTest() { + compareSrc(26, "trace(\"forTest\");\r\n" + + "var i = 0;\r\n" + + "while(i < 10)\r\n" + + "{\r\n" + + "trace(\"hello:\" + i);\r\n" + + "i++;\r\n" + + "}\r\n" + ); + } + + @Test + public void frame27_whileTest() { + compareSrc(27, "trace(\"whileTest\");\r\n" + + "var i = 0;\r\n" + + "while(i < 10)\r\n" + + "{\r\n" + + "trace(\"hello:\" + i);\r\n" + + "i++;\r\n" + + "}\r\n" + ); + } + + @Test + public void frame28_forWithContinueTest() { + compareSrc(28, "trace(\"forWithContinueTest\");\r\n" + + "var i = 0;\r\n" + + "for(; i < 10; i++)\r\n" + + "{\r\n" + + "trace(\"hello:\" + i);\r\n" + + "if(i == 5)\r\n" + + "{\r\n" + + "trace(\"i==5\");\r\n" + + "if(i == 7)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"hawk\");\r\n" + + "}\r\n" + + "trace(\"end of the loop\");\r\n" + + "}\r\n" + ); + } + + @Test + public void frame29_doWhileTest() { + compareSrc(29, "trace(\"doWhileTest\");\r\n" + + "var i = 0;\r\n" + + "do\r\n" + + "{\r\n" + + "trace(\"i=\" + i);\r\n" + + "i++;\r\n" + + "}\r\n" + + "while(i < 10);\r\n" + + "trace(\"end\");\r\n" + ); + } + + @Test + public void frame30_switchTest() { + compareSrc(30, "trace(\"switchTest\");\r\n" + + "var i = 5;\r\n" + + "switch(i)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "case 1:\r\n" + + "trace(\"one\");\r\n" + + "break;\r\n" + + "case 2:\r\n" + + "trace(\"two\");\r\n" + + "case 3:\r\n" + + "trace(\"three\");\r\n" + + "break;\r\n" + + "case 4:\r\n" + + "trace(\"four\");\r\n" + + "break;\r\n" + + "default:\r\n" + + "trace(\"default clause\");\r\n" + + "}\r\n" + + "trace(\"scriptend\");\r\n" + ); + } + + @Test + public void frame31_strictEqualsTest() { + compareSrc(31, "trace(\"strictEqualsTest\");\r\n" + + "var i = 5;\r\n" + + "if(i === 5)\r\n" + + "{\r\n" + + "trace(\"equals strict\");\r\n" + + "}\r\n" + + "if(i !== 5)\r\n" + + "{\r\n" + + "trace(\"not equals strict\");\r\n" + + "}\r\n" + ); + } + + @Test + public void frame32_switchForTest() { + compareSrc(32, "trace(\"switchForTest\");\r\n" + + "var i = 0;\r\n" + + "for(; i < 10; i++)\r\n" + + "{\r\n" + + "switch(i)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "trace(\"zero\");\r\n" + + "continue;\r\n" + + "case 5:\r\n" + + "trace(\"five\");\r\n" + + "break;\r\n" + + "case 10:\r\n" + + "trace(\"ten\");\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "if(i == 7)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"one\");\r\n" + + "default:\r\n" + + "trace(\"def\");\r\n" + + "}\r\n" + + "trace(\"before loop end\");\r\n" + + "}\r\n" + ); + } + + @Test + public void frame33_functionTest() { + compareSrc(33, "function hello(what, second)\r\n" + + "{\r\n" + + "trace(\"hello \" + what + \"! \" + second);\r\n" + + "}\r\n" + + "trace(\"functionTest\");\r\n" + + "hello(\"friend\",7);\r\n" + ); + } + + @Test + public void frame34_multipleConditionsTest() { + compareSrc(34, "trace(\"multipleConditionsTest\");\r\n" + + "var k = 5;\r\n" + + "if(k == 7 && k == 8)\r\n" + + "{\r\n" + + "trace(\"first\");\r\n" + + "}\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"second\");\r\n" + + "}\r\n" + + "trace(\"finish\");\r\n" + ); + } + + @Test + public void frame35_multipleConditions2Test() { + compareSrc(35, "trace(\"multipleConditions2Test\");\r\n" + + "var k = 5;\r\n" + + "if(k == 7 && k == 8)\r\n" + + "{\r\n" + + "trace(\"first\");\r\n" + + "}\r\n" + + "if(k == 9 || k == 6)\r\n" + + "{\r\n" + + "trace(\"second\");\r\n" + + "}\r\n" + + "trace(\"finish\");\r\n" + ); + } + + @Test + public void frame36_chainedAssignmentsTest() { + compareSrc(36, "trace(\"chainedAssignmentsTest\");\r\n" + + "var a = 7;\r\n" + + "var b = 8;\r\n" + + "var c = 9;\r\n" + + "var d = c = b = a = 10;\r\n" + + "trace(d);\r\n" + ); + } + + @Test + public void frame37_objectsTest() { + compareSrc(37, "trace(\"objectsTest\");\r\n" + + "var flashBox = new Box(box1);\r\n" + + "_root.onEnterFrame = function()\r\n" + + "{\r\n" + + "flashBox.moveUp();\r\n" + + "};\r\n" + + "var ship = new Ship(200);\r\n" + + "var enemy = new Enemy(56);\r\n" + + "ship.moveDown(0.5);\r\n" + + "ship.moveUp(0.2);\r\n" + + "enemy.moveRight(230);\r\n" + + "enemy.moveLeft(100);\r\n" + + "var mt = new com.jpexs.MyTest();\r\n" + + "mt.test();\r\n" + + "var c = new Cox(box1);\r\n" + ); + } + + @Test + public void frame38_doWhile2Test() { + compareSrc(38, "trace(\"doWhile2Test\");\r\n" + + "var k = 5;\r\n" + + "do\r\n" + + "{\r\n" + + "k++;\r\n" + + "if(k == 7)\r\n" + + "{\r\n" + + "k = 5 * k;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "k = 5 + k;\r\n" + + "}\r\n" + + "}\r\n" + + "while(k < 9);\r\n" + ); + } + + @Test + public void frame39_whileAndTest() { + compareSrc(39, "trace(\"whileAndTest\");\r\n" + + "var a = 5;\r\n" + + "var b = 10;\r\n" + + "while(a < 10 && b > 1)\r\n" + + "{\r\n" + + "a++;\r\n" + + "b--;\r\n" + + "}\r\n" + + "a = 7;\r\n" + + "b = 9;\r\n" + ); + } + + @Test + public void frame40_forInTest() { + compareSrc(40, "function testForIn()\r\n" + + "{\r\n" + + "var _loc1_ = [];\r\n" + + "for(var _loc2_ in _loc1_)\r\n" + + "{\r\n" + + "if(_loc2_ > 3)\r\n" + + "{\r\n" + + "if(_loc2_ == 5)\r\n" + + "{\r\n" + + "return 7;\r\n" + + "}\r\n" + + "return 8;\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"forInTest\");\r\n" + + "trace(testForIn());\r\n" + + "var arr = [];\r\n" + + "for(var a in arr)\r\n" + + "{\r\n" + + "trace(a);\r\n" + + "}\r\n" + ); + } + + @Test + public void frame41_tryTest() { + compareSrc(41, "trace(\"tryTest\");\r\n" + + "var k = 5;\r\n" + + "try\r\n" + + "{\r\n" + + "k = Infinity;\r\n" + + "}\r\n" + + "catch(e)\r\n" + + "{\r\n" + + "trace(\"bug \" + e);\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"huu\");\r\n" + + "}\r\n" + + "trace(\"next\");\r\n" + + "try\r\n" + + "{\r\n" + + "k = 6;\r\n" + + "}\r\n" + + "catch(e)\r\n" + + "{\r\n" + + "trace(\"bug2 \" + e);\r\n" + + "}\r\n" + + "trace(\"next2\");\r\n" + + "var k = 5;\r\n" + + "try\r\n" + + "{\r\n" + + "k = Infinity;\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"final\");\r\n" + + "}\r\n" + + "trace(\"end\");\r\n" + ); + } + + @Test + public void frame42_indicesTest() { + compareSrc(42, "trace(\"indicesTest\");\r\n" + + "var k = [1,2,3];\r\n" + + "var b = k[1];\r\n" + + "trace(b);\r\n" + ); + } + + @Test + public void frame43_incDecTest() { + compareSrc(43, "function tst()\r\n" + + "{\r\n" + + "return 1;\r\n" + + "}\r\n" + + "trace(\"incDecTest\");\r\n" + + "var i = 5;\r\n" + + "var b = i++;\r\n" + + "var c = --i + 5;\r\n" + + "trace(\"a:\" + a + \" b:\" + b + \" c:\" + c);\r\n" + + "var arr = [1,2,3];\r\n" + + "arr[tst()]++;\r\n" + + "var d = arr[tst()];\r\n" + + "trace(d);\r\n" + ); + } + + @Test + public void frame44_chainedAssignments2Test() { + compareSrc(44, "trace(\"chainedAssignments2Test\");\r\n" + + "var a = 5;\r\n" + + "var b = 6;\r\n" + + "var c = 7;\r\n" + + "var d = c = b = a = 4;\r\n" + + "if((d = c = b = a = 7) > 2)\r\n" + + "{\r\n" + + "trace(d);\r\n" + + "}\r\n" + + "trace(d + 1);\r\n" + + "var i = 0;\r\n" + + "while(i < 5)\r\n" + + "{\r\n" + + "if(i == 7)\r\n" + + "{\r\n" + + "}\r\n" + + "i++;\r\n" + + "}\r\n" + ); + } + + @Test + public void frame45_function2Test() { + compareSrc(45, "function a()\r\n" + + "{\r\n" + + "trace(\"hi\");\r\n" + + "var _loc1_ = 5;\r\n" + + "if(_loc1_ == 7)\r\n" + + "{\r\n" + + "return undefined;\r\n" + + "}\r\n" + + "_loc1_ = _loc1_ * 9;\r\n" + + "trace(_loc1_);\r\n" + + "}\r\n" + + "trace(\"function2Test\");\r\n" + ); + } + + @Test + public void frame46_tryFunctionTest() { + compareSrc(46, "function testtry()\r\n" + + "{\r\n" + + "var _loc1_ = 5;\r\n" + + "try\r\n" + + "{\r\n" + + "if(_loc1_ == 3)\r\n" + + "{\r\n" + + "return undefined;\r\n" + + "}\r\n" + + "if(_loc1_ == 4)\r\n" + + "{\r\n" + + "throw new Error();\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "_loc1_ = 7;\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e)\r\n" + + "{\r\n" + + "trace(\"error\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"finally\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"tryFunctionTest\");\r\n" + ); + } + + @Test + public void frame47_ternarTest() { + compareSrc(47, "trace(\"ternarTest\");\r\n" + + "var a = 5;\r\n" + + "var b = a != 4?3:2;\r\n" + + "trace(b);\r\n" + ); + } + + @Test + public void frame48_forInInTest() { + compareSrc(48, "function tst()\r\n" + + "{\r\n" + + "var _loc2_ = [];\r\n" + + "_loc2_[0] = [];\r\n" + + "for(var _loc3_ in _loc2_)\r\n" + + "{\r\n" + + "for(var _loc1_ in _loc3_)\r\n" + + "{\r\n" + + "if(_loc1_ == 5)\r\n" + + "{\r\n" + + "return 5;\r\n" + + "}\r\n" + + "}\r\n" + + "if(_loc3_ == 8)\r\n" + + "{\r\n" + + "return 3;\r\n" + + "}\r\n" + + "}\r\n" + + "return 8;\r\n" + + "}\r\n" + + "trace(\"forInInTest\");\r\n" + + "tst();\r\n" + ); + } + + @Test + public void frame49_registersFuncTest() { + compareSrc(49, "function tst(px)\r\n" + + "{\r\n" + + "var _loc1_ = 57;\r\n" + + "_loc1_ = _loc1_ * 27;\r\n" + + "}\r\n" + + "trace(\"registersFuncTest\");\r\n" + + "tst(5);\r\n" + + "var s = String(5);\r\n" + ); + } + + @Test + public void frame50_ifFrameLoadedTest() { + compareSrc(50, "trace(\"ifFrameLoadedTest\");\r\n" + + "ifFrameLoaded(9)\r\n" + + "{\r\n" + + "trace(\"loaded\");\r\n" + + "}\r\n" + ); + } + + @Test + public void frame51_function3Test() { + compareSrc(51, "function tst()\r\n" + + "{\r\n" + + "var _loc1_ = 5;\r\n" + + "c = _loc1_ = 8;\r\n" + + "trace(\"hi\");\r\n" + + "trace(_loc1_);\r\n" + + "if((e = d = f = c = 9) > 5)\r\n" + + "{\r\n" + + "trace(\"dd\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"function3Test\");\r\n" + + "var c = 7;\r\n" + + "var d = 7;\r\n" + + "var e = 8;\r\n" + + "tst();\r\n" + ); + } + + @Test + public void frame52_commaOperatorTest() { + compareSrc(52, "trace(\"commaOperatorTest\");\r\n" + + "var a = 0;\r\n" + + "var b = 0;\r\n" + + "var c = 0;\r\n" + + "while(true)\r\n" + + "{\r\n" + + "a++;\r\n" + + "b = b + 2;\r\n" + + "if(c < 10)\r\n" + + "{\r\n" + + "trace(c);\r\n" + + "c++;\r\n" + + "continue;\r\n" + + "}\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"konec\");\r\n" + ); + } + + @Test + public void frame53_commaOperator2Test() { + compareSrc(53, "trace(\"commaOperator2Test\");\r\n" + + "var k = 8;\r\n" + + "do\r\n" + + "{\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"h\");\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"f\");\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"b\");\r\n" + + "}\r\n" + + "trace(\"gg\");\r\n" + + "}\r\n" + + "while(k++, k < 10);\r\n" + + "trace(\"ss\");\r\n" + ); + } + + @Test + public void frame54_function4Test() { + compareSrc(54, "function tst()\r\n" + + "{\r\n" + + "var _loc1_ = 5;\r\n" + + "while(_loc1_ < 10)\r\n" + + "{\r\n" + + "if(_loc1_ == 5)\r\n" + + "{\r\n" + + "if(_loc1_ == 6)\r\n" + + "{\r\n" + + "return true;\r\n" + + "}\r\n" + + "_loc1_ = _loc1_ + 1;\r\n" + + "continue;\r\n" + + "}\r\n" + + "return false;\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"function4Test\");\r\n" + + "tst();\r\n" + ); + } + + @Test + public void frame55_pushTest() { + compareSrc(55, "trace(\"pushTest\");\r\n" + + "53;" + ); + } + + @Test + public void frame56_commaOperator3Test() { + compareSrc(56, "trace(\"commaOperator3Test\");\r\n" + + "var k = 1;\r\n" + + "while(true)\r\n" + + "{\r\n" + + "k++;\r\n" + + "if(k < 10)\r\n" + + "{\r\n" + + "k = k * 5;\r\n" + + "trace(k);\r\n" + + "continue;\r\n" + + "}\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"end\");\r\n" + ); + } + + @Test + public void frame57_commaOperator4Test() { + compareSrc(57, "trace(\"commaOperator4Test\");\r\n" + + "var k = 0;\r\n" + + "do\r\n" + + "{\r\n" + + "trace(k);\r\n" + + "if(k == 8)\r\n" + + "{\r\n" + + "trace(\"a\");\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"d\");\r\n" + + "trace(\"b\");\r\n" + + "}\r\n" + + "k++;\r\n" + + "}\r\n" + + "while(k = k + 5, k < 20);\r\n" + + "trace(\"end\");\r\n" + ); + } + + @Test + public void frame58_globalFunctionsTest() { + compareSrc(58, "function tst(p1)\r\n" + + "{\r\n" + + "trace(\"test\");\r\n" + + "}\r\n" + + "trace(\"globalFunctionsTest\");\r\n" + + "var k = Array(1,2,3);\r\n" + + "var a = 1;\r\n" + + "var b = Boolean(a);\r\n" + + "call(5);\r\n" + + "var c = \"A\";\r\n" + + "clearInterval(5);\r\n" + + "clearTimeout(4);\r\n" + + "var mc;\r\n" + + "duplicateMovieClip(mc,\"copy\",16389);\r\n" + + "a = escape(\"how\");\r\n" + + "var f = a;\r\n" + + "fscommand(\"alert(\\\"hi\\\");\");\r\n" + + "a = mc._alpha;\r\n" + + "a = getTimer();\r\n" + + "getURL(\"http://localhost/\",\"wnd\",\"POST\");\r\n" + + "a = getVersion();\r\n" + + "gotoAndPlay(5);\r\n" + + "gotoAndStop(8);\r\n" + + "ifFrameLoaded(4)\r\n" + + "{\r\n" + + "trace(\"loaded\");\r\n" + + "}\r\n" + + "a = int(f);\r\n" + + "a = isFinite(f);\r\n" + + "a = isNaN(f);\r\n" + + "a = length(f);\r\n" + + "loadMovie(\"http://localhost/test.swf\",a,\"GET\");\r\n" + + "loadMovieNum(\"http://localhost/test.swf\",5,\"GET\");\r\n" + + "loadVariables(\"http://localhost/vars.txt\",a,\"GET\");\r\n" + + "loadVariablesNum(\"http://localhost/vars.txt\",4,\"GET\");\r\n" + + "a = mbchr(f);\r\n" + + "a = mblength(f);\r\n" + + "a = mbord(f);\r\n" + + "a = mbsubstring(\"aaaa\",5,4);\r\n" + + "MMExecute(\"destroyPC\");\r\n" + + "nextFrame();\r\n" + + "gotoAndStop(1);\r\n" + + "a = Number(f);\r\n" + + "a = Object(f);\r\n" + + "a = ord(f);\r\n" + + "a = parseFloat(f);\r\n" + + "a = parseInt(f,16);\r\n" + + "play();\r\n" + + "prevFrame();\r\n" + + "gotoAndStop(1);\r\n" + + "print(mc,\"bframe\");\r\n" + + "printAsBitmap(mc,\"bframe\");\r\n" + + "printAsBitmapNum(5,\"bframe\");\r\n" + + "printNum(4,\"bframe\");\r\n" + + "a = random(10);\r\n" + + "removeMovieClip(mc);\r\n" + + "setInterval(tst,5,f);\r\n" + + "mc._alpha = 25;\r\n" + + "setTimeout(tst,5,f);\r\n" + + "showRedrawRegions(false,0);\r\n" + + "startDrag(mc,1,5,5,6,6);\r\n" + + "stop();\r\n" + + "stopAllSounds();\r\n" + + "stopDrag();\r\n" + + "a = String(f);\r\n" + + "a = \"aa\";\r\n" + + "targetPath(f);\r\n" + + "tellTarget(mc)\r\n" + + "{\r\n" + + "trace(\"told\");\r\n" + + "}\r\n" + + "toggleHighQuality();\r\n" + + "a = unescape(f);\r\n" + + "unloadMovie(mc);\r\n" + + "unloadMovieNum(4);\r\n" + + "updateAfterEvent();\r\n" + ); + } + + @Test + public void frame59_unaryOpTest() { + compareSrc(59, "trace(\"unaryOpTest\");\r\n" + + "var a = 5;\r\n" + + "var c = ~a;\r\n" + + "var d = ~(a + c);\r\n" + + "var e = - c;\r\n" + ); + } +} diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex b/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex index a1760063a..870340e7c 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex @@ -17,8 +17,8 @@ package jsyntaxpane.lexers; import jsyntaxpane.Token; import jsyntaxpane.TokenType; - -%% + +%% %public %class ActionScriptLexer @@ -58,7 +58,7 @@ InputCharacter = [^\r\n] WhiteSpace = {LineTerminator} | [ \t\f]+ /* comments */ -Comment = {TraditionalComment} | {EndOfLineComment} +Comment = {TraditionalComment} | {EndOfLineComment} TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/" EndOfLineComment = "//" {InputCharacter}* {LineTerminator}? @@ -92,13 +92,13 @@ HexDigit = [0-9a-fA-F] OctIntegerLiteral = 0+ [1-3]? {OctDigit} {1,15} OctDigit = [0-7] - -/* floating point literals */ + +/* floating point literals */ DoubleLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}? -FLit1 = [0-9]+ \. [0-9]* -FLit2 = \. [0-9]+ -FLit3 = [0-9]+ +FLit1 = [0-9]+ \. [0-9]* +FLit2 = \. [0-9]+ +FLit3 = [0-9]+ Exponent = [eE] [+-]? [0-9]+ NewVector = "new" {WhiteSpace}* "<" @@ -108,6 +108,7 @@ StringCharacter = [^\r\n\"\\] SingleCharacter = [^\r\n\'\\] OIdentifierCharacter = [^\r\n\u00A7\\] +Preprocessor = \u00A7\u00A7 {Identifier} %state STRING, CHARLITERAL, XMLSTARTTAG, XML, OIDENTIFIER @@ -174,114 +175,117 @@ OIdentifierCharacter = [^\r\n\u00A7\\] "}" { return token(TokenType.OPERATOR, -CURLY); } "[" { return token(TokenType.OPERATOR, BRACKET); } "]" { return token(TokenType.OPERATOR, -BRACKET); } - ";" | - "," | - "..." | - "." | - "=" | - ">" | + ";" | + "," | + "..." | + "." | + "=" | + ">" | "<" | - "!" | - "~" | - "?" | - ":" | - "==" | - "<=" | - ">=" | - "!=" | - "&&" | - "||" | - "++" | - "--" | - "+" | - "-" | - "*" | - "/" | - "&" | - "|" | - "^" | - "%" | - "<<" | - ">>" | - ">>>" | - "+=" | - "-=" | - "*=" | - "/=" | - "&=" | - "|=" | - "^=" | - "%=" | - "<<=" | - ">>=" | + "!" | + "~" | + "?" | + ":" | + "==" | + "<=" | + ">=" | + "!=" | + "&&" | + "||" | + "++" | + "--" | + "+" | + "-" | + "*" | + "/" | + "&" | + "|" | + "^" | + "%" | + "<<" | + ">>" | + ">>>" | + "+=" | + "-=" | + "*=" | + "/=" | + "&=" | + "|=" | + "^=" | + "%=" | + "<<=" | + ">>=" | ">>>=" | - "as" | - "delete" | - "instanceof" | - "is" | - "::" | - "new" | - "typeof" | - "void" | + "as" | + "delete" | + "instanceof" | + "is" | + "::" | + "new" | + "typeof" | + "void" | {NewVector} | - "@" { return token(TokenType.OPERATOR); } - + "@" { return token(TokenType.OPERATOR); } + /* string literal */ - \" { - yybegin(STRING); - tokenStart = yychar; - tokenLength = 1; + \" { + yybegin(STRING); + tokenStart = yychar; + tokenLength = 1; } - "\u00A7" { - yybegin(OIDENTIFIER); - tokenStart = yychar; - tokenLength = 1; + {Preprocessor} { + return token(TokenType.REGEX); + } + "\u00A7" { + yybegin(OIDENTIFIER); + tokenStart = yychar; + tokenLength = 1; } /* character literal */ - \' { - yybegin(CHARLITERAL); - tokenStart = yychar; - tokenLength = 1; + \' { + yybegin(CHARLITERAL); + tokenStart = yychar; + tokenLength = 1; } /* numeric literals */ {DecIntegerLiteral} | - + {HexIntegerLiteral} | - + {OctIntegerLiteral} | - + {DoubleLiteral} | {DoubleLiteral}[dD] { return token(TokenType.NUMBER); } - + // JavaDoc comments need a state so that we can highlight the @ controls /* comments */ {Comment} { return token(TokenType.COMMENT); } /* whitespace */ - {WhiteSpace} { } + {WhiteSpace} { } {TypeNameSpec} { return token(TokenType.IDENTIFIER); } - {XMLBeginOneTag} { yybegin(XML); + {XMLBeginOneTag} { yybegin(XML); tokenStart = yychar; - tokenLength = yylength(); - String s=yytext(); + tokenLength = yylength(); + String s=yytext(); s=s.substring(1,s.length()-1); if(s.contains(" ")){ s=s.substring(0,s.indexOf(" ")); } xmlTagName = s; } - /*{XMLBeginTag} { yybegin(XMLSTARTTAG); + /*{XMLBeginTag} { yybegin(XMLSTARTTAG); tokenStart = yychar; - tokenLength = yylength(); - String s=yytext(); + tokenLength = yylength(); + String s=yytext(); xmlTagName = s.substring(1); }*/ - /* identifiers */ - {Identifier} { return token(TokenType.IDENTIFIER); } + /* identifiers */ + {Identifier} { return token(TokenType.IDENTIFIER); } } { @@ -293,7 +297,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] {XMLBeginOneTag} { tokenLength += yylength();} {XMLEndTag} { tokenLength += yylength(); String endtagname=yytext(); - endtagname=endtagname.substring(2,endtagname.length()-1); + endtagname=endtagname.substring(2,endtagname.length()-1); if(endtagname.equals(xmlTagName)){ yybegin(YYINITIAL); return token(TokenType.STRING, tokenStart, tokenLength); @@ -303,16 +307,16 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \" { - yybegin(YYINITIAL); + \" { + yybegin(YYINITIAL); // length also includes the trailing quote return token(TokenType.STRING, tokenStart, tokenLength + 1); } - + {StringCharacter}+ { tokenLength += yylength(); } \\[0-3]?{OctDigit}?{OctDigit} { tokenLength += yylength(); } - + /* escape sequences */ \\. { tokenLength += 2; } @@ -320,15 +324,15 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - "\u00A7" { - yybegin(YYINITIAL); + "\u00A7" { + yybegin(YYINITIAL); // length also includes the trailing quote return token(TokenType.REGEX, tokenStart, tokenLength + 1); } - + {OIdentifierCharacter}+ { tokenLength += yylength(); } - + /* escape sequences */ \\. { tokenLength += 2; } @@ -336,14 +340,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \' { - yybegin(YYINITIAL); + \' { + yybegin(YYINITIAL); // length also includes the trailing quote return token(TokenType.STRING, tokenStart, tokenLength + 1); } - + {SingleCharacter}+ { tokenLength += yylength(); } - + /* escape sequences */ \\. { tokenLength += 2; } From c85c60f1d7a54c4205c0bddff71a00c0501532b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 7 Jun 2015 09:37:48 +0200 Subject: [PATCH 02/20] AS3: Better Alchemy / DomainMemory instruction handling --- .../instructions/alchemy/AlchemyTypeIns.java | 27 ++++ .../avm2/instructions/alchemy/Lf32Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Lf64Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Li16Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Li32Ins.java | 116 ++++++++--------- .../abc/avm2/instructions/alchemy/Li8Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Sf32Ins.java | 118 +++++++++--------- .../avm2/instructions/alchemy/Sf64Ins.java | 118 +++++++++--------- .../avm2/instructions/alchemy/Si16Ins.java | 118 +++++++++--------- .../avm2/instructions/alchemy/Si32Ins.java | 118 +++++++++--------- .../abc/avm2/instructions/alchemy/Si8Ins.java | 118 +++++++++--------- .../avm2/instructions/alchemy/Sxi16Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Sxi1Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Sxi8Ins.java | 116 ++++++++--------- .../abc/avm2/model/AlchemyLoadAVM2Item.java | 52 +++++++- .../avm2/model/AlchemySignExtendAVM2Item.java | 40 ++++-- .../abc/avm2/model/AlchemyStoreAVM2Item.java | 47 ++++++- .../flash/abc/types/traits/TraitClass.java | 7 ++ 18 files changed, 915 insertions(+), 776 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java new file mode 100644 index 000000000..2f7890b38 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +/** + * + * @author JPEXS + */ +public interface AlchemyTypeIns { + + public static final String ALCHEMY_PACKAGE = "avm2.intrinsics.memory"; + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf32Ins.java index 6739f5d58..215c47c7f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf32Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Lf32Ins extends InstructionDefinition { - - public Lf32Ins() { - super(0x38, "lf32", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Lf32Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Lf32Ins() { + super(0x38, "lf32", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'f', 32)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf64Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf64Ins.java index 33b88d996..9b971e5a5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf64Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf64Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Lf64Ins extends InstructionDefinition { - - public Lf64Ins() { - super(0x39, "lf64", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Lf64Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Lf64Ins() { + super(0x39, "lf64", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'f', 64)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li16Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li16Ins.java index 327dcafe8..44a3c0267 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li16Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li16Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Li16Ins extends InstructionDefinition { - - public Li16Ins() { - super(0x36, "li16", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Li16Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Li16Ins() { + super(0x36, "li16", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'i', 16)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li32Ins.java index 1f9086b89..e38c32477 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li32Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Li32Ins extends InstructionDefinition { - - public Li32Ins() { - super(0x37, "li32", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Li32Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Li32Ins() { + super(0x37, "li32", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'i', 32)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li8Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li8Ins.java index 3d4d7aef6..6987e579a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li8Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li8Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Li8Ins extends InstructionDefinition { - - public Li8Ins() { - super(0x35, "li8", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Li8Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Li8Ins() { + super(0x35, "li8", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'i', 8)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java index 3600a9a38..c4b738610 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sf32Ins extends InstructionDefinition { - - public Sf32Ins() { - super(0x3D, "sf32", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sf32Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sf32Ins() { + super(0x3D, "sf32", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'f', 32)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java index b3ab4aafd..aff8f6ed1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sf64Ins extends InstructionDefinition { - - public Sf64Ins() { - super(0x3E, "sf64", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sf64Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sf64Ins() { + super(0x3E, "sf64", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'f', 64)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java index 94a030a38..b8719b254 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Si16Ins extends InstructionDefinition { - - public Si16Ins() { - super(0x3B, "si16", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Si16Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Si16Ins() { + super(0x3B, "si16", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'i', 16)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java index 2c02aed1f..ef7124bd1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Si32Ins extends InstructionDefinition { - - public Si32Ins() { - super(0x3C, "si32", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Si32Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Si32Ins() { + super(0x3C, "si32", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'i', 32)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java index 32a14bc3b..9a10cda59 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Si8Ins extends InstructionDefinition { - - public Si8Ins() { - super(0x3A, "si8", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Si8Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Si8Ins() { + super(0x3A, "si8", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'i', 8)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi16Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi16Ins.java index b52e0d8f0..fa63166b5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi16Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi16Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sxi16Ins extends InstructionDefinition { - - public Sxi16Ins() { - super(0x52, "sxi_16", new int[]{}, false); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem value = stack.pop(); - stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sxi16Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sxi16Ins() { + super(0x52, "sxi16", new int[]{}, false); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem value = stack.pop(); + stack.push(new AlchemySignExtendAVM2Item(ins, value, 16)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi1Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi1Ins.java index 434b7e479..e3a792330 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi1Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi1Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sxi1Ins extends InstructionDefinition { - - public Sxi1Ins() { - super(0x50, "sxi_1", new int[]{}, false); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem value = stack.pop(); - stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sxi1Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sxi1Ins() { + super(0x50, "sxi1", new int[]{}, false); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem value = stack.pop(); + stack.push(new AlchemySignExtendAVM2Item(ins, value, 1)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi8Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi8Ins.java index 90096eafd..3b6976421 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi8Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi8Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sxi8Ins extends InstructionDefinition { - - public Sxi8Ins() { - super(0x51, "sxi_8", new int[]{}, false); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem value = stack.pop(); - stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sxi8Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sxi8Ins() { + super(0x51, "sxi8", new int[]{}, false); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem value = stack.pop(); + stack.push(new AlchemySignExtendAVM2Item(ins, value, 8)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyLoadAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyLoadAVM2Item.java index 73525a4f6..b00b58b2a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyLoadAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyLoadAVM2Item.java @@ -16,11 +16,21 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf64Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li8Ins; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; /** * @@ -28,25 +38,57 @@ import com.jpexs.decompiler.graph.model.LocalData; */ public class AlchemyLoadAVM2Item extends AVM2Item { - private final String name; + private final char type; + private final int size; private final GraphTargetItem ofs; - public AlchemyLoadAVM2Item(GraphSourceItem instruction, GraphTargetItem ofs, String name) { + public AlchemyLoadAVM2Item(GraphSourceItem instruction, GraphTargetItem ofs, char type, int size) { super(instruction, PRECEDENCE_PRIMARY); - this.name = name; this.ofs = ofs; + this.type = type; + this.size = size; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("op_" + name + "("); + writer.append("l" + type + size + "("); ofs.toString(writer, localData); - return writer.append(") /*Alchemy*/"); + return writer.append(")"); + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + String ts = "" + type + size; + InstructionDefinition def = null; + switch (ts) { + case "i8": + def = new Li8Ins(); + break; + case "i16": + def = new Li16Ins(); + break; + case "i32": + def = new Li32Ins(); + break; + case "f": + def = new Lf32Ins(); + break; + case "f32": + def = new Lf64Ins(); + break; + } + return toSourceMerge(localData, generator, ofs, ins(def)); } @Override public GraphTargetItem returnType() { + switch (type) { + case 'i': + return new TypeItem("int"); + case 'f': + return new TypeItem("Number"); + } return TypeItem.UNBOUNDED; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemySignExtendAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemySignExtendAVM2Item.java index ed725c54a..18095c337 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemySignExtendAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemySignExtendAVM2Item.java @@ -12,14 +12,23 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi1Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi8Ins; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; /** * @@ -27,28 +36,45 @@ import com.jpexs.decompiler.graph.model.LocalData; */ public class AlchemySignExtendAVM2Item extends AVM2Item { - private final String name; + private final int size; - public AlchemySignExtendAVM2Item(GraphSourceItem instruction, GraphTargetItem value, String name) { + public AlchemySignExtendAVM2Item(GraphSourceItem instruction, GraphTargetItem value, int size) { super(instruction, PRECEDENCE_PRIMARY); - this.name = name; this.value = value; + this.size = size; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("op_" + name + "("); + writer.append("si" + size + "("); value.toString(writer, localData); - return writer.append(") /*Alchemy*/"); + return writer.append(")"); } @Override public GraphTargetItem returnType() { - return TypeItem.UNBOUNDED; + return new TypeItem("int"); } @Override public boolean hasReturnValue() { return true; } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + InstructionDefinition def = null; + switch (size) { + case 1: + def = new Sxi1Ins(); + break; + case 8: + def = new Sxi8Ins(); + break; + case 16: + def = new Sxi16Ins(); + break; + } + return toSourceMerge(localData, generator, value, ins(def)); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyStoreAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyStoreAVM2Item.java index d36499f38..e26570594 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyStoreAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyStoreAVM2Item.java @@ -16,11 +16,21 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf64Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si8Ins; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; /** * @@ -28,24 +38,26 @@ import com.jpexs.decompiler.graph.model.LocalData; */ public class AlchemyStoreAVM2Item extends AVM2Item { - private final String name; + private final char type; + private final int size; private final GraphTargetItem ofs; - public AlchemyStoreAVM2Item(GraphSourceItem instruction, GraphTargetItem value, GraphTargetItem ofs, String name) { + public AlchemyStoreAVM2Item(GraphSourceItem instruction, GraphTargetItem value, GraphTargetItem ofs, char type, int size) { super(instruction, PRECEDENCE_PRIMARY); - this.name = name; this.ofs = ofs; this.value = value; + this.type = type; + this.size = size; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("op_" + name + "("); + writer.append("s" + type + size + "("); ofs.toString(writer, localData); writer.append(","); value.toString(writer, localData); - return writer.append(") /*Alchemy*/"); + return writer.append(")"); } @Override @@ -57,4 +69,29 @@ public class AlchemyStoreAVM2Item extends AVM2Item { public boolean hasReturnValue() { return false; } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + String ts = "" + type + size; + InstructionDefinition def = null; + switch (ts) { + case "i8": + def = new Si8Ins(); + break; + case "i16": + def = new Si16Ins(); + break; + case "i32": + def = new Si32Ins(); + break; + case "f32": + def = new Sf32Ins(); + break; + case "f64": + def = new Sf64Ins(); + break; + } + return toSourceMerge(localData, generator, ofs, ins(def)); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 7a91873ce..19599b0fc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ClassPath; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.AlchemyTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns; @@ -270,6 +271,12 @@ public class TraitClass extends Trait implements TraitWithSlot { parseImportsUsagesFromMultiname(abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames); } for (AVM2Instruction ins : body.getCode().code) { + if (ins.definition instanceof AlchemyTypeIns) { + String nimport = AlchemyTypeIns.ALCHEMY_PACKAGE + "." + ins.definition.instructionName; + if (!imports.contains(nimport)) { + imports.add(nimport); + } + } if (ins.definition instanceof NewFunctionIns) { if (ins.operands[0] != method_index) { if (!visitedMethods.contains(ins.operands[0])) { From a5933ca43fcd8caff9283d619bf60580823d2a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 7 Jun 2015 13:46:15 +0200 Subject: [PATCH 03/20] Better multi packs handling (Alchemy) - direct editing allowed Better package/class splitting for obfuscated names --- .../com/jpexs/decompiler/flash/abc/ABC.java | 67 +- .../decompiler/flash/abc/ScriptPack.java | 1 + .../model/clauses/DeclarationAVM2Item.java | 4 +- .../abc/avm2/model/clauses/TryAVM2Item.java | 2 +- .../parser/script/AVM2SourceGenerator.java | 30 +- .../parser/script/ActionScriptParser.java | 106 +- .../abc/avm2/parser/script/ClassAVM2Item.java | 5 +- .../avm2/parser/script/InterfaceAVM2Item.java | 5 +- .../avm2/parser/script/PackageAVM2Item.java | 5 +- .../avm2/parser/script/PropertyAVM2Item.java | 3 +- .../parser/script/UnresolvedAVM2Item.java | 40 +- .../flash/abc/types/InstanceInfo.java | 280 +- .../flash/abc/types/MethodInfo.java | 2 +- .../decompiler/flash/abc/types/Multiname.java | 19 +- .../flash/abc/types/ScriptInfo.java | 3 + .../flash/abc/types/traits/Trait.java | 400 +-- .../flash/abc/types/traits/TraitClass.java | 114 +- .../abc/usages/ClassNameMultinameUsage.java | 2 +- .../abc/usages/InsideClassMultinameUsage.java | 2 +- .../flash/configuration/Configuration.java | 4 +- .../jpexs/decompiler/graph/DottedChain.java | 106 + .../com/jpexs/decompiler/graph/TypeItem.java | 50 +- .../src/com/jpexs/helpers/Helper.java | 2671 +++++++-------- src/com/jpexs/decompiler/flash/gui/Main.java | 3001 ++++++++--------- .../decompiler/flash/gui/MainFrameRibbon.java | 11 +- .../jpexs/decompiler/flash/gui/MainPanel.java | 2 + .../decompiler/flash/gui/abc/ABCPanel.java | 10 +- .../flash/gui/abc/DecompiledEditorPane.java | 12 +- .../decompiler/flash/gui/abc/UsageFrame.java | 358 +- .../flash/gui/debugger/DebuggerTools.java | 4 +- .../locales/AdvancedSettingsDialog.properties | 8 +- 31 files changed, 3737 insertions(+), 3590 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index 10a27d85e..40e9f4584 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -59,17 +59,21 @@ import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.utf8.Utf8PrintWriter; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; +import javafx.collections.transformation.SortedList; public class ABC { @@ -107,7 +111,7 @@ public class ABC { public ABCContainerTag parentTag; /* Map from multiname index of namespace value to namespace name**/ - private Map namespaceMap; + private Map namespaceMap; public ABC(ABCContainerTag tag) { this.parentTag = tag; @@ -323,7 +327,7 @@ public class ABC { int mIndex = body.getCode().code.get(ip).operands[0]; if (mIndex > 0) { Multiname m = constants.getMultiname(mIndex); - if (m.getNameWithNamespace(constants, true).equals("flash.utils.getDefinitionByName")) { + if (m.getNameWithNamespace(constants).equals("flash.utils.getDefinitionByName")) { if (ip > 0) { if (body.getCode().code.get(ip - 1).definition instanceof PushStringIns) { int strIndex = body.getCode().code.get(ip - 1).operands[0]; @@ -812,16 +816,16 @@ public class ABC { } } - private Map getNamespaceMap() { + private Map getNamespaceMap() { if (namespaceMap == null) { - Map map = new HashMap<>(); + Map map = new HashMap<>(); for (ScriptInfo si : script_info) { for (Trait t : si.traits.traits) { if (t instanceof TraitSlotConst) { TraitSlotConst s = ((TraitSlotConst) t); if (s.isNamespace()) { String key = constants.getNamespace(s.value_index).getName(constants, true); // assume not null - String val = constants.getMultiname(s.name_index).getNameWithNamespace(constants, true); + DottedChain val = constants.getMultiname(s.name_index).getNameWithNamespace(constants); map.put(key, val); } } @@ -855,15 +859,15 @@ public class ABC { return bodyIdxFromMethodIdx; } - public String nsValueToName(String value) { + public DottedChain nsValueToName(String value) { if (getNamespaceMap().containsKey(value)) { return getNamespaceMap().get(value); } else { String ns = getDeobfuscation().builtInNs(value); if (ns == null) { - return ""; + return new DottedChain(""); } else { - return ns; + return new DottedChain(ns); } } } @@ -1037,8 +1041,8 @@ public class ABC { public int findClassByName(String name) { for (int c = 0; c < instance_info.size(); c++) { - String s = constants.getMultiname(instance_info.get(c).name_index).getNameWithNamespace(constants, true); - if (name.equals(s)) { + DottedChain s = constants.getMultiname(instance_info.get(c).name_index).getNameWithNamespace(constants); + if (name.equals(s.toString())) { return c; } } @@ -1229,31 +1233,54 @@ public class ABC { method_info.remove(index); } - public void replaceScriptPack(ScriptPack pack, String as) throws AVM2ParseException, CompilationException, IOException, InterruptedException { + public boolean replaceScriptPack(ScriptPack pack, String as) throws AVM2ParseException, CompilationException, IOException, InterruptedException { String scriptName = pack.getPathScriptName() + ".as"; int oldIndex = pack.scriptIndex; int newIndex = script_info.size(); String documentClass = getSwf().getDocumentClass(); boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString()); + boolean isSimple = pack.isSimple; + ScriptInfo si = script_info.get(oldIndex); - si.delete(this, true); - int newClassIndex = instance_info.size(); - for (Trait t : si.traits.traits) { - if (t instanceof TraitClass) { - TraitClass tc = (TraitClass) t; - newClassIndex = tc.class_info + 1; + if (isSimple) { + si.delete(this, true); + } else { + for (int t : pack.traitIndices) { + si.traits.traits.get(t).delete(this, true); } } + + int newClassIndex = instance_info.size(); + for (int t : pack.traitIndices) { + if (si.traits.traits.get(t) instanceof TraitClass) { + TraitClass tc = (TraitClass) si.traits.traits.get(t); + newClassIndex = tc.class_info + 1; + } + + } List otherAbcs = new ArrayList<>(pack.allABCs); + otherAbcs.remove(this); ActionScriptParser.compile(as, this, otherAbcs, isDocumentClass, scriptName, newClassIndex); - // Move newly added script to its position - script_info.set(oldIndex, script_info.get(newIndex)); - script_info.remove(newIndex); + + if (isSimple) { + // Move newly added script to its position + script_info.set(oldIndex, script_info.get(newIndex)); + script_info.remove(newIndex); + } else { + script_info.get(newIndex).setModified(true); + //Note: Is deleting traits safe? + List todel = new ArrayList<>(new TreeSet<>(pack.traitIndices)); + for (int i = todel.size() - 1; i >= 0; i--) { + si.traits.traits.remove((int) todel.get(i)); + } + } + script_info.get(oldIndex).setModified(true); pack(); // removes old classes/methods ((Tag) parentTag).setModified(true); + return !isSimple; } public void pack() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 9e5485e48..3ee9e7620 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -61,6 +61,7 @@ public class ScriptPack extends AS3ClassTreeItem { public final List traitIndices; private final ClassPath path; + public boolean isSimple = false; @Override public SWF getSwf() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java index 32d64eaad..956ecd8d6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java @@ -85,7 +85,7 @@ public class DeclarationAVM2Item extends AVM2Item { if (lti.value instanceof ConvertAVM2Item) { coerType = ((ConvertAVM2Item) lti.value).type; } - srcData.declaredType = (coerType instanceof TypeItem) ? ((TypeItem) coerType).fullTypeName : "*"; + srcData.declaredType = (coerType instanceof TypeItem) ? ((TypeItem) coerType).fullTypeName.toPrintableString() : "*"; writer.append("var "); writer.append(localName); writer.append(":"); @@ -97,7 +97,7 @@ public class DeclarationAVM2Item extends AVM2Item { SetSlotAVM2Item ssti = (SetSlotAVM2Item) assignment; srcData.localName = ssti.getNameAsStr(localData); srcData.declaration = true; - srcData.declaredType = (type instanceof TypeItem) ? ((TypeItem) type).fullTypeName : "*"; + srcData.declaredType = (type instanceof TypeItem) ? ((TypeItem) type).fullTypeName.toPrintableString() : "*"; writer.append("var "); ssti.getName(writer, localData); writer.append(":"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java index 3e223f4a1..ab8a69b17 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java @@ -96,7 +96,7 @@ public class TryAVM2Item extends AVM2Item implements Block { int eti = catchExceptions.get(e).type_index; - data.declaredType = eti <= 0 ? "*" : localData.constantsAvm2.constant_multiname.get(eti).getNameWithNamespace(localData.constantsAvm2, true); + data.declaredType = eti <= 0 ? "*" : localData.constantsAvm2.constant_multiname.get(eti).getNameWithNamespace(localData.constantsAvm2).toPrintableString(); writer.hilightSpecial(localName, HighlightSpecialType.TRY_NAME, e, data); writer.append(":"); writer.hilightSpecial(catchExceptions.get(e).getTypeName(localData.constantsAvm2, localData.fullyQualifiedNames), HighlightSpecialType.TRY_TYPE, e); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 0aaf4f006..82a7859b4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -108,6 +108,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.Loop; @@ -1194,7 +1195,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return abc; } - public void generateClass(List importedClasses, List sinitVariables, boolean staticNeedsActivation, List staticInit, List openedNamespaces, int namespace, int initScope, String pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List traitItems, Reference class_index) throws AVM2ParseException, CompilationException { + public void generateClass(List importedClasses, List sinitVariables, boolean staticNeedsActivation, List staticInit, List openedNamespaces, int namespace, int initScope, String pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List traitItems, Reference class_index) throws AVM2ParseException, CompilationException { localData.currentClass = name; localData.pkg = pkg; List ret = new ArrayList<>(); @@ -1706,7 +1707,7 @@ public class AVM2SourceGenerator implements SourceGenerator { TraitSlotConst tsc = (TraitSlotConst) mbody.traits.traits.get(i); GraphTargetItem type = TypeItem.UNBOUNDED; if (tsc.type_index > 0) { - type = new TypeItem(abc.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(abc.constants, true)); + type = new TypeItem(abc.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(abc.constants)); } NameAVM2Item d = new NameAVM2Item(type, 0, tsc.getName(abc).getName(abc.constants, new ArrayList(), true), NameAVM2Item.getDefaultValue("" + type), true, new ArrayList()); d.setSlotNumber(tsc.slot_id); @@ -1867,7 +1868,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return null; } - private int genNs(List importedClasses, String pkg, String custom, int namespace, List openedNamespaces, SourceGeneratorLocalData localData, int line) throws CompilationException { + private int genNs(List importedClasses, String pkg, String custom, int namespace, List openedNamespaces, SourceGeneratorLocalData localData, int line) throws CompilationException { if (custom != null) { PropertyAVM2Item prop = new PropertyAVM2Item(null, custom, abc, allABCs, openedNamespaces, new ArrayList()); Reference value = new Reference<>(null); @@ -1878,11 +1879,9 @@ public class AVM2SourceGenerator implements SourceGenerator { } if (!resolved) { - String customPkg = ""; - String fullCustom = ""; - for (String imp : importedClasses) { - if (imp.endsWith("." + custom)) { - customPkg = imp.substring(0, imp.lastIndexOf('.')); + DottedChain fullCustom = null; + for (DottedChain imp : importedClasses) { + if (imp.getLast().equals(custom)) { fullCustom = imp; break; } @@ -1895,7 +1894,7 @@ public class AVM2SourceGenerator implements SourceGenerator { for (ScriptInfo si : a.script_info) { for (Trait t : si.traits.traits) { Multiname m = t.getName(a); - if (fullCustom.equals(m.getNameWithNamespace(a.constants, true))) { + if (fullCustom != null && fullCustom.equals(m.getNameWithNamespace(a.constants))) { if (t instanceof TraitSlotConst) { if (((TraitSlotConst) t).isNamespace()) { Namespace ns = a.constants.getNamespace(((TraitSlotConst) t).value_index); @@ -1914,7 +1913,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return namespace; } - public void generateTraitsPhase2(List importedClasses, String pkg, List items, Trait[] traits, List openedNamespaces, SourceGeneratorLocalData localData) throws CompilationException { + public void generateTraitsPhase2(List importedClasses, String pkg, List items, Trait[] traits, List openedNamespaces, SourceGeneratorLocalData localData) throws CompilationException { for (int k = 0; k < items.size(); k++) { GraphTargetItem item = items.get(k); if (traits[k] == null) { @@ -2145,7 +2144,7 @@ public class AVM2SourceGenerator implements SourceGenerator { ScriptInfo si = new ScriptInfo(); localData.currentScript = si; Trait[] traitArr = generateTraitsPhase1(null, null, true, localData, commands, si.traits, class_index); - generateTraitsPhase2(new ArrayList(), null/*FIXME*/, commands, traitArr, new ArrayList(), localData); + generateTraitsPhase2(new ArrayList(), null/*FIXME*/, commands, traitArr, new ArrayList(), localData); MethodInfo mi = new MethodInfo(new int[0], 0, 0, 0, new ValueKind[0], new int[0]); MethodBody mb = new MethodBody(); mb.method_info = abc.addMethodInfo(mi); @@ -2457,12 +2456,9 @@ public class AVM2SourceGenerator implements SourceGenerator { TypeItem type = (TypeItem) typeItem; - String name = type.fullTypeName; - String pkg = ""; - if (name.contains(".")) { - pkg = name.substring(0, name.lastIndexOf('.')); - name = name.substring(name.lastIndexOf('.') + 1); - } + DottedChain dname = type.fullTypeName; + String pkg = dname.getWithoutLast().toString(); + String name = dname.getLast(); for (InstanceInfo ii : abc.instance_info) { Multiname mname = abc.constants.constant_multiname.get(ii.name_index); if (mname != null && name.equals(mname.getName(abc.constants, new ArrayList(), true))) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java index e302990ae..95f4fd6ac 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java @@ -86,6 +86,7 @@ import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.Loop; import com.jpexs.decompiler.graph.TypeItem; @@ -143,7 +144,7 @@ public class ActionScriptParser { return uniqLast; } - private List commands(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, AVM2ParseException { + private List commands(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, AVM2ParseException { List ret = new ArrayList<>(); if (debugMode) { System.out.println("commands:"); @@ -158,7 +159,7 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem type(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem type(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List variables) throws IOException, AVM2ParseException { ParsedSymbol s = lex(); if (s.type == SymbolType.MULTIPLY) { return new UnboundedTypeItem(); @@ -173,7 +174,7 @@ public class ActionScriptParser { return t; } - private GraphTargetItem memberOrCall(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem memberOrCall(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { if (debugMode) { System.out.println("memberOrCall:"); } @@ -222,7 +223,7 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem applyType(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem applyType(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { GraphTargetItem ret = obj; ParsedSymbol s = lex(); if (s.type == SymbolType.TYPENAME) { @@ -249,7 +250,7 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem member(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem member(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { if (debugMode) { System.out.println("member:"); } @@ -285,7 +286,7 @@ public class ActionScriptParser { s = lex(); GraphTargetItem ns = null; if (s.type == SymbolType.NAMESPACE_OP) { - ns = new UnresolvedAVM2Item(new ArrayList(), importedClasses, false, null, lexer.yyline(), propName, null, openedNamespaces); + ns = new UnresolvedAVM2Item(new ArrayList(), importedClasses, false, null, lexer.yyline(), new DottedChain(propName), null, openedNamespaces); variables.add((UnresolvedAVM2Item) ns); s = lex(); if (s.type == SymbolType.BRACKET_OPEN) { @@ -316,28 +317,31 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem name(TypeItem thisType, String pkg, Reference needsActivation, boolean typeOnly, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, List importedClasses) throws IOException, AVM2ParseException { + private GraphTargetItem name(TypeItem thisType, String pkg, Reference needsActivation, boolean typeOnly, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, List importedClasses) throws IOException, AVM2ParseException { ParsedSymbol s = lex(); - String name = ""; + DottedChain name = new DottedChain(); + String name2 = ""; if (s.type == SymbolType.ATTRIBUTE) { - name += "@"; + name2 += "@"; s = lex(); } expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.THIS, SymbolType.SUPER, SymbolType.STRING_OP); - name += s.value.toString(); + name2 += s.value.toString(); s = lex(); boolean attrBracket = false; + name.parts.add(name2); while (s.isType(SymbolType.DOT)) { - name += s.value.toString(); //. or :: + //name += s.value.toString(); //. or :: s = lex(); + name2 = ""; if (s.type == SymbolType.ATTRIBUTE) { - name += "@"; + name2 += "@"; s = lex(); if (s.type == SymbolType.MULTIPLY) { - name += s.value.toString(); + name2 += s.value.toString(); } else if (s.group == SymbolGroup.IDENTIFIER) { - name += s.value.toString(); + name2 += s.value.toString(); } else { if (s.type != SymbolType.BRACKET_OPEN) { throw new AVM2ParseException("Attribute identifier or bracket expected", lexer.yyline()); @@ -347,19 +351,16 @@ public class ActionScriptParser { } } else { expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE); - name += s.value.toString(); + name2 += s.value.toString(); } + name.parts.add(name2); s = lex(); } String nsname = null; String nsprop = null; GraphTargetItem nspropItem = null; if (s.type == SymbolType.NAMESPACE_OP) { - if (name.contains(".")) { - nsname = name.substring(name.lastIndexOf('.') + 1); - } else { - nsname = name; - } + nsname = name.getLast(); s = lex(); if (s.group == SymbolGroup.IDENTIFIER) { nsprop = s.value.toString(); @@ -367,16 +368,12 @@ public class ActionScriptParser { nspropItem = expression(thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); expectedType(SymbolType.BRACKET_CLOSE); } - if (name.contains(".")) { - name = name.substring(0, name.lastIndexOf('.')); - } else { - name = null; - } + name = name.getWithoutLast(); s = lex(); } GraphTargetItem ret = null; - if (name != null) { + if (!name.parts.isEmpty()) { UnresolvedAVM2Item unr = new UnresolvedAVM2Item(new ArrayList(), importedClasses, typeOnly, null, lexer.yyline(), name, null, openedNamespaces); //unr.setIndex(index); variables.add(unr); @@ -387,7 +384,7 @@ public class ActionScriptParser { if (attr) { nsname = nsname.substring(1); } - UnresolvedAVM2Item ns = new UnresolvedAVM2Item(new ArrayList(), importedClasses, typeOnly, null, lexer.yyline(), nsname, null, openedNamespaces); + UnresolvedAVM2Item ns = new UnresolvedAVM2Item(new ArrayList(), importedClasses, typeOnly, null, lexer.yyline(), new DottedChain(nsname), null, openedNamespaces); variables.add(ns); ret = new NamespacedAVM2Item(ns, nsprop, nspropItem, ret, attr, openedNamespaces, null); } @@ -442,7 +439,7 @@ public class ActionScriptParser { return ret; } - private List call(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private List call(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { List ret = new ArrayList<>(); //expected(SymbolType.PARENT_OPEN); //MUST BE HANDLED BY CALLER ParsedSymbol s = lex(); @@ -457,12 +454,12 @@ public class ActionScriptParser { return ret; } - private MethodAVM2Item method(String pkg, boolean isInterface, String customAccess, Reference needsActivation, List importedClasses, boolean override, boolean isFinal, TypeItem thisType, List openedNamespaces, boolean isStatic, int namespace, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { + private MethodAVM2Item method(String pkg, boolean isInterface, String customAccess, Reference needsActivation, List importedClasses, boolean override, boolean isFinal, TypeItem thisType, List openedNamespaces, boolean isStatic, int namespace, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { FunctionAVM2Item f = function(pkg, isInterface, needsActivation, importedClasses, namespace, thisType, openedNamespaces, functionName, isMethod, variables); return new MethodAVM2Item(f.pkg, f.isInterface, customAccess, f.needsActivation, f.hasRest, f.line, override, isFinal, isStatic, f.namespace, functionName, f.paramTypes, f.paramNames, f.paramValues, f.body, f.subvariables, f.retType); } - private FunctionAVM2Item function(String pkg, boolean isInterface, Reference needsActivation, List importedClasses, int namespace, TypeItem thisType, List openedNamespaces, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { + private FunctionAVM2Item function(String pkg, boolean isInterface, Reference needsActivation, List importedClasses, int namespace, TypeItem thisType, List openedNamespaces, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { openedNamespaces = new ArrayList<>(openedNamespaces); //local copy int line = lexer.yyline(); ParsedSymbol s; @@ -543,7 +540,7 @@ public class ActionScriptParser { return new FunctionAVM2Item(pkg, isInterface, needsActivation2.getVal(), namespace, hasRest, line, functionName, paramTypes, paramNames, paramValues, body, subvariables, retType); } - private GraphTargetItem traits(String scriptName, boolean scriptTraits, List sinitVariables, Reference sinitNeedsActivation, List staticInitializer, List importedClasses, int privateNs, int protectedNs, int publicNs, int packageInternalNs, int protectedStaticNs, List openedNamespaces, String pkg, String classNameStr, boolean isInterface, List traits) throws AVM2ParseException, IOException, CompilationException { + private GraphTargetItem traits(String scriptName, boolean scriptTraits, List sinitVariables, Reference sinitNeedsActivation, List staticInitializer, List importedClasses, int privateNs, int protectedNs, int publicNs, int packageInternalNs, int protectedStaticNs, List openedNamespaces, String pkg, String classNameStr, boolean isInterface, List traits) throws AVM2ParseException, IOException, CompilationException { ParsedSymbol s; GraphTargetItem constr = null; TypeItem thisType = pkg == null && classNameStr == null ? null : new TypeItem(pkg == null || "".equals(pkg) ? classNameStr : pkg + "." + classNameStr); @@ -891,7 +888,7 @@ public class ActionScriptParser { return constr; } - private GraphTargetItem classTraits(String scriptName, int gpublicNs, String pkg, List importedClasses, boolean isDynamic, boolean isFinal, List openedNamespaces, String packageName, int namespace, boolean isInterface, String nameStr, GraphTargetItem extendsStr, List implementsStr, List variables) throws IOException, AVM2ParseException, CompilationException { + private GraphTargetItem classTraits(String scriptName, int gpublicNs, String pkg, List importedClasses, boolean isDynamic, boolean isFinal, List openedNamespaces, String packageName, int namespace, boolean isInterface, String nameStr, GraphTargetItem extendsStr, List implementsStr, List variables) throws IOException, AVM2ParseException, CompilationException { GraphTargetItem ret = null; @@ -1048,7 +1045,7 @@ public class ActionScriptParser { } } - private List xmltag(TypeItem thisType, String pkg, Reference usesVars, List openedTags, Reference closedVarTags, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private List xmltag(TypeItem thisType, String pkg, Reference usesVars, List openedTags, Reference closedVarTags, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { ParsedSymbol s = null; List rets = new ArrayList<>(); //GraphTargetItem ret = null; @@ -1177,7 +1174,7 @@ public class ActionScriptParser { return rets; } - private GraphTargetItem xml(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem xml(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { List openedTags = new ArrayList<>(); int closedVarTags = 0; @@ -1188,7 +1185,7 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem command(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem command(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables) throws IOException, AVM2ParseException { LexBufferer buf = new LexBufferer(); lexer.addListener(buf); GraphTargetItem ret = null; @@ -1671,7 +1668,7 @@ public class ActionScriptParser { } - private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { return expression(thisType, pkg, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, allowRemainder, variables); } @@ -1703,7 +1700,7 @@ public class ActionScriptParser { return ret; } - /*private GraphTargetItem expressionRemainder(TypeItem thisType, String pkg, Reference needsActivation, List openedNamespaces, GraphTargetItem expr, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, List importedClasses) throws IOException, AVM2ParseException { + /*private GraphTargetItem expressionRemainder(TypeItem thisType, String pkg, Reference needsActivation, List openedNamespaces, GraphTargetItem expr, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, List importedClasses) throws IOException, AVM2ParseException { GraphTargetItem ret = null; ParsedSymbol s = lex(); @@ -1739,7 +1736,7 @@ public class ActionScriptParser { return false; } - private int brackets(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List ret, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private int brackets(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List ret, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { ParsedSymbol s = lex(); int arrCnt = 0; if (s.type == SymbolType.BRACKET_OPEN) { @@ -1763,7 +1760,7 @@ public class ActionScriptParser { return arrCnt; } - private GraphTargetItem commaExpression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forInLevel, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem commaExpression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forInLevel, List variables) throws IOException, AVM2ParseException { GraphTargetItem cmd = null; List expr = new ArrayList<>(); ParsedSymbol s; @@ -1785,7 +1782,7 @@ public class ActionScriptParser { return new CommaExpressionItem(null, expr); } - private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { GraphTargetItem prim = expressionPrimary(thisType, pkg, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables); if (prim == null) { return null; @@ -1815,7 +1812,7 @@ public class ActionScriptParser { return lookahead; } - private GraphTargetItem expression1(GraphTargetItem lhs, int min_precedence, TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expression1(GraphTargetItem lhs, int min_precedence, TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { if (debugMode) { System.out.println("expression1:"); } @@ -2028,7 +2025,7 @@ public class ActionScriptParser { return lhs; } - private GraphTargetItem expressionPrimary(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expressionPrimary(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { if (debugMode) { System.out.println("primary:"); } @@ -2278,39 +2275,34 @@ public class ActionScriptParser { s = lex(); } - List importedClasses = new ArrayList<>(); + List importedClasses = new ArrayList<>(); s = lex(); while (s.type == SymbolType.IMPORT) { - String impPackage = ""; - String impName = null; boolean all = false; s = lex(); expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER); - impName = s.value.toString(); + DottedChain imp = new DottedChain(); + imp.parts.add(s.value.toString()); s = lex(); + boolean isStar = false; while (s.type == SymbolType.DOT) { - if (!"".equals(impPackage)) { - impPackage += "."; - } - impPackage += impName; s = lex(); if (s.type == SymbolType.MULTIPLY) { - impName = null; + isStar = true; s = lex(); break; } expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER); - - impName = s.value.toString(); + imp.parts.add(s.value.toString()); s = lex(); } - if (impName == null) { - openedNamespaces.add(abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(impPackage, true)), 0, true)); + if (isStar) { + openedNamespaces.add(abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(imp.toString(), true)), 0, true)); } else { - importedClasses.add(impPackage + "." + impName); + importedClasses.add(imp); } expected(s, lexer.yyline(), SymbolType.SEMICOLON); @@ -2348,7 +2340,7 @@ public class ActionScriptParser { openedNamespaces.add(publicNs = abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId("", true)), 0, true)); List items = new ArrayList<>(); - traits(fileName, true, new ArrayList(), new Reference<>(false), new ArrayList(), new ArrayList(), scriptPrivateNs, 0, publicNs, 0, 0, openedNamespaces, null, null, false, items); + traits(fileName, true, new ArrayList(), new Reference<>(false), new ArrayList(), new ArrayList(), scriptPrivateNs, 0, publicNs, 0, 0, openedNamespaces, null, null, false, items); return items; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java index 719e7102c..cd49a855d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.Block; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -54,7 +55,7 @@ public class ClassAVM2Item extends AVM2Item implements Block { public List sinitVariables; - public List importedClasses; + public List importedClasses; public String pkg; @@ -67,7 +68,7 @@ public class ClassAVM2Item extends AVM2Item implements Block { return ret; } - public ClassAVM2Item(List importedClasses, String pkg, List openedNamespaces, int protectedNs, boolean isDynamic, boolean isFinal, int namespace, String className, GraphTargetItem extendsOp, List implementsOp, List staticInit, boolean staticInitActivation, List sinitVariables, GraphTargetItem constructor, List traits) { + public ClassAVM2Item(List importedClasses, String pkg, List openedNamespaces, int protectedNs, boolean isDynamic, boolean isFinal, int namespace, String className, GraphTargetItem extendsOp, List implementsOp, List staticInit, boolean staticInitActivation, List sinitVariables, GraphTargetItem constructor, List traits) { super(null, NOPRECEDENCE); this.importedClasses = importedClasses; this.pkg = pkg; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/InterfaceAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/InterfaceAVM2Item.java index a21b5cdcb..70d5625e4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/InterfaceAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/InterfaceAVM2Item.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; @@ -43,9 +44,9 @@ public class InterfaceAVM2Item extends AVM2Item { public String pkg; - public List importedClasses; + public List importedClasses; - public InterfaceAVM2Item(List importedClasses, String pkg, List openedNamespaces, boolean isFinal, int namespace, String name, List superInterfaces, List traits) { + public InterfaceAVM2Item(List importedClasses, String pkg, List openedNamespaces, boolean isFinal, int namespace, String name, List superInterfaces, List traits) { super(null, NOPRECEDENCE); this.importedClasses = importedClasses; this.pkg = pkg; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PackageAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PackageAVM2Item.java index 5a69d0668..65e16378d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PackageAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PackageAVM2Item.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; @@ -34,11 +35,11 @@ public class PackageAVM2Item extends AVM2Item { public String packageName; - public List importedClasses = new ArrayList<>(); + public List importedClasses = new ArrayList<>(); public int publicNs = 0; - public PackageAVM2Item(int publicNs, List importedClasses, String packageName, List items) { + public PackageAVM2Item(int publicNs, List importedClasses, String packageName, List items) { super(null, NOPRECEDENCE); this.publicNs = publicNs; this.importedClasses = importedClasses; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java index 42e9f8c95..18d57acea 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java @@ -44,6 +44,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.SourceGenerator; @@ -115,7 +116,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } return new ApplyTypeAVM2Item(null, obj, params); } else { - return new TypeItem(m.getNameWithNamespace(constants, true)); + return new TypeItem(m.getNameWithNamespace(constants)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java index 2548eaf0e..f7a57bc6c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; @@ -48,7 +49,7 @@ import java.util.List; */ public class UnresolvedAVM2Item extends AssignableAVM2Item { - private String name; + private DottedChain name; private int nsKind = -1; @@ -65,7 +66,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { private final boolean mustBeType; - public List importedClasses; + public List importedClasses; public List scopeStack = new ArrayList<>(); @@ -128,7 +129,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { */ public void appendName(String name) { - this.name += "." + name; + this.name.parts.add(name); } public void setDefinition(boolean definition) { @@ -150,15 +151,15 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { this.assignedValue = storeValue; } - public String getVariableName() { + public DottedChain getVariableName() { return name; } - public void setVariableName(String name) { + public void setVariableName(DottedChain name) { this.name = name; } - public UnresolvedAVM2Item(List subtypes, List importedClasses, boolean mustBeType, GraphTargetItem type, int line, String name, GraphTargetItem storeValue, List openedNamespaces) { + public UnresolvedAVM2Item(List subtypes, List importedClasses, boolean mustBeType, GraphTargetItem type, int line, DottedChain name, GraphTargetItem storeValue, List openedNamespaces) { super(storeValue); this.name = name; this.assignedValue = storeValue; @@ -264,7 +265,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { if (resolved != null) { return resolved.toString(); } - return name; + return name.toString(); } @Override @@ -290,14 +291,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } public GraphTargetItem resolve(GraphTargetItem thisType, List paramTypes, List paramNames, ABC abc, List otherAbcs, List callStack, List variables) throws CompilationException { - List parts = new ArrayList<>(); - if (name.contains(".")) { - String[] partsArr = name.split("\\."); - parts.addAll(Arrays.asList(partsArr)); - } else { - parts.add(name); - } - + List parts = name.parts; if (scopeStack.isEmpty()) { //Everything is multiname property in with command //search for variable @@ -326,13 +320,9 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } } //Search for types in imported classes - for (String imp : importedClasses) { - String impName = imp; - String impPkg = ""; - if (impName.contains(".")) { - impPkg = impName.substring(0, impName.lastIndexOf('.')); - impName = impName.substring(impName.lastIndexOf('.') + 1); - } + for (DottedChain imp : importedClasses) { + String impName = imp.getLast(); + if (impName.equals(parts.get(0))) { TypeItem ret = new TypeItem(imp); resolved = ret; @@ -354,13 +344,13 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { allAbcs.add(abc); allAbcs.addAll(otherAbcs); for (int i = 0; i < parts.size(); i++) { - String fname = Helper.joinStrings(parts.subList(0, i + 1), "."); + DottedChain fname = new DottedChain(parts.subList(0, i + 1)); //Helper.joinStrings(parts.subList(0, i + 1), "."); for (ABC a : allAbcs) { for (int c = 0; c < a.instance_info.size(); c++) { if (a.instance_info.get(c).deleted) { continue; } - if (a.instance_info.get(c).name_index > 0 && fname.equals(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants, true))) { + if (a.instance_info.get(c).name_index > 0 && fname.equals(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants))) { if (!subtypes.isEmpty() && parts.size() > i + 1) { continue; } @@ -400,7 +390,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { if (!subtypes.isEmpty() && parts.size() > 1) { continue; } - TypeItem ret = new TypeItem(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants, true)); + TypeItem ret = new TypeItem(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants)); /*for (String s : subtypes) { UnresolvedAVM2Item su = new UnresolvedAVM2Item(new ArrayList(), importedClasses, true, null, line, s, null, openedNamespaces); su.resolve(thisType, paramTypes, paramNames, abc, otherAbcs, callStack, variables); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java index aa4c969ce..21aa19a6b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java @@ -1,140 +1,140 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.types; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.List; - -public class InstanceInfo { - - public int name_index; - - public int super_index; - - public int flags; // 1 = sealed, 0 = dynamic, 2 = final, 4 = interface, 8 = ProtectedNs - - public int protectedNS; //if flags & 8 - - public int[] interfaces; - - public int iinit_index; // MethodInfo - constructor - - public Traits instance_traits; - - public static final int CLASS_SEALED = 1; //not dynamic - - public static final int CLASS_FINAL = 2; - - public static final int CLASS_INTERFACE = 4; - - public static final int CLASS_PROTECTEDNS = 8; - - @Internal - public boolean deleted; - - public InstanceInfo() { - instance_traits = new Traits(); - } - - public InstanceInfo(Traits traits) { - instance_traits = traits; - } - - @Override - public String toString() { - return "name_index=" + name_index + " super_index=" + super_index + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(); - } - - public String toString(ABC abc, List fullyQualifiedNames) { - String supIndexStr = "[nothing]"; - if (super_index > 0) { - supIndexStr = abc.constants.getMultiname(super_index).toString(abc.constants, fullyQualifiedNames); - } - return "name_index=" + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " super_index=" + supIndexStr + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(abc, fullyQualifiedNames); - } - - public GraphTextWriter getClassHeaderStr(GraphTextWriter writer, ABC abc, List fullyQualifiedNames, boolean allowPrivate) { - String modifiers; - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - modifiers = ns.getPrefix(abc); - if (!allowPrivate && modifiers.equals("private")) { - modifiers = ""; - } - if (!modifiers.isEmpty()) { - modifiers += " "; - } - - if (isFinal()) { - modifiers += "final "; - } - if (!isInterface() && isDynamic()) { - modifiers += "dynamic "; - } - String objType = "class "; - if (isInterface()) { - objType = "interface "; - } - - writer.appendNoHilight(modifiers + objType); - writer.hilightSpecial(abc.constants.getMultiname(name_index).getName(abc.constants, new ArrayList()/* No full names here*/, false), HighlightSpecialType.CLASS_NAME); - - if (super_index > 0) { - String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants, true); - writer.appendNoHilight(" extends "); - writer.hilightSpecial(abc.constants.getMultiname(super_index).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); - } - if (interfaces.length > 0) { - if (isInterface()) { - writer.appendNoHilight(" extends "); - } else { - writer.appendNoHilight(" implements "); - } - for (int i = 0; i < interfaces.length; i++) { - if (i > 0) { - writer.append(", "); - } - String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants, true); - writer.hilightSpecial(abc.constants.getMultiname(interfaces[i]).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); - } - } - - return writer; - } - - public Multiname getName(AVM2ConstantPool constants) { - return constants.getMultiname(name_index); - } - - public boolean isInterface() { - return ((flags & CLASS_INTERFACE) == CLASS_INTERFACE); - } - - public boolean isDynamic() { - return (flags & CLASS_SEALED) == 0; - } - - public boolean isFinal() { - return (flags & CLASS_FINAL) == CLASS_FINAL; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.types; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.helpers.Helper; +import java.util.ArrayList; +import java.util.List; + +public class InstanceInfo { + + public int name_index; + + public int super_index; + + public int flags; // 1 = sealed, 0 = dynamic, 2 = final, 4 = interface, 8 = ProtectedNs + + public int protectedNS; //if flags & 8 + + public int[] interfaces; + + public int iinit_index; // MethodInfo - constructor + + public Traits instance_traits; + + public static final int CLASS_SEALED = 1; //not dynamic + + public static final int CLASS_FINAL = 2; + + public static final int CLASS_INTERFACE = 4; + + public static final int CLASS_PROTECTEDNS = 8; + + @Internal + public boolean deleted; + + public InstanceInfo() { + instance_traits = new Traits(); + } + + public InstanceInfo(Traits traits) { + instance_traits = traits; + } + + @Override + public String toString() { + return "name_index=" + name_index + " super_index=" + super_index + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(); + } + + public String toString(ABC abc, List fullyQualifiedNames) { + String supIndexStr = "[nothing]"; + if (super_index > 0) { + supIndexStr = abc.constants.getMultiname(super_index).toString(abc.constants, fullyQualifiedNames); + } + return "name_index=" + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " super_index=" + supIndexStr + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(abc, fullyQualifiedNames); + } + + public GraphTextWriter getClassHeaderStr(GraphTextWriter writer, ABC abc, List fullyQualifiedNames, boolean allowPrivate) { + String modifiers; + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + modifiers = ns.getPrefix(abc); + if (!allowPrivate && modifiers.equals("private")) { + modifiers = ""; + } + if (!modifiers.isEmpty()) { + modifiers += " "; + } + + if (isFinal()) { + modifiers += "final "; + } + if (!isInterface() && isDynamic()) { + modifiers += "dynamic "; + } + String objType = "class "; + if (isInterface()) { + objType = "interface "; + } + + writer.appendNoHilight(modifiers + objType); + writer.hilightSpecial(abc.constants.getMultiname(name_index).getName(abc.constants, new ArrayList()/* No full names here*/, false), HighlightSpecialType.CLASS_NAME); + + if (super_index > 0) { + String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants).toPrintableString(); + writer.appendNoHilight(" extends "); + writer.hilightSpecial(abc.constants.getMultiname(super_index).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); + } + if (interfaces.length > 0) { + if (isInterface()) { + writer.appendNoHilight(" extends "); + } else { + writer.appendNoHilight(" implements "); + } + for (int i = 0; i < interfaces.length; i++) { + if (i > 0) { + writer.append(", "); + } + String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants).toPrintableString(); + writer.hilightSpecial(abc.constants.getMultiname(interfaces[i]).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); + } + } + + return writer; + } + + public Multiname getName(AVM2ConstantPool constants) { + return constants.getMultiname(name_index); + } + + public boolean isInterface() { + return ((flags & CLASS_INTERFACE) == CLASS_INTERFACE); + } + + public boolean isDynamic() { + return (flags & CLASS_SEALED) == 0; + } + + public boolean isFinal() { + return (flags & CLASS_FINAL) == CLASS_FINAL; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java index 5452250a7..4003aa7a4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java @@ -310,7 +310,7 @@ public class MethodInfo { } String ptype = "*"; if (param_types[i] > 0) { - ptype = constants.getMultiname(param_types[i]).getNameWithNamespace(constants, false); + ptype = constants.getMultiname(param_types[i]).getNameWithNamespace(constants).toPrintableString(); } HighlightData pdata = new HighlightData(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java index f43b499d1..da15bae78 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java @@ -19,7 +19,9 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Helper; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -288,23 +290,28 @@ public class Multiname { } else { String name = constants.getString(name_index); if (fullyQualifiedNames != null && fullyQualifiedNames.contains(name)) { - return getNameWithNamespace(constants, raw); + DottedChain dc = getNameWithNamespace(constants); + return raw ? dc.toString() : dc.toPrintableString(); } return (isAttribute() ? "@" : "") + (raw ? name : IdentifiersDeobfuscation.printIdentifier(true, name)); } } - public String getNameWithNamespace(AVM2ConstantPool constants, boolean raw) { + public DottedChain getNameWithNamespace(AVM2ConstantPool constants) { StringBuilder ret = new StringBuilder(); Namespace ns = getNamespace(constants); + List chain = new ArrayList<>(); if (ns != null) { - String nsname = ns.getName(constants, raw); + String nsname = ns.getName(constants, true); if (nsname != null && !nsname.isEmpty()) { - ret.append(nsname).append("."); + String parts[] = nsname.split("\\."); + for (String p : parts) { + chain.add(p); + } } } - ret.append(getName(constants, null, raw)); - return ret.toString(); + chain.add(getName(constants, null, true)); + return new DottedChain(chain); } public Namespace getNamespace(AVM2ConstantPool constants) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java index 6a96ba792..42b6e7b63 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java @@ -88,6 +88,9 @@ public class ScriptInfo { } } } + if (ret.size() == 1) { + ret.get(0).isSimple = true; + } return ret; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 632faa6e0..d0de03bfb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -1,200 +1,200 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.types.traits; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.ClassPath; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.Namespace; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.NulWriter; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.helpers.Helper; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -public abstract class Trait implements Serializable { - - private static final int[] EMPTY_METADATA_ARRAY = new int[0]; - - public int name_index; - - public int kindType; - - public int kindFlags; - - public int[] metadata = EMPTY_METADATA_ARRAY; - - public long fileOffset; - - public byte[] bytes; - - public static final int ATTR_Final = 0x1; - - public static final int ATTR_Override = 0x2; - - public static final int ATTR_Metadata = 0x4; - - public static final int TRAIT_SLOT = 0; - - public static final int TRAIT_METHOD = 1; - - public static final int TRAIT_GETTER = 2; - - public static final int TRAIT_SETTER = 3; - - public static final int TRAIT_CLASS = 4; - - public static final int TRAIT_FUNCTION = 5; - - public static final int TRAIT_CONST = 6; - - public abstract void delete(ABC abc, boolean d); - - public String getModifiers(ABC abc, boolean isStatic) { - String ret = ""; - if ((kindFlags & ATTR_Override) > 0) { - ret += "override"; - } - Multiname m = getName(abc); - if (m != null) { - String nsname = ""; - //if (abc.constants.getNamespace(m.namespace_index).kind == Namespace.KIND_NAMESPACE) { - { - for (ABCContainerTag abcTag : abc.getAbcTags()) { - if (m.namespace_index == -1) { - break; - } - nsname = abcTag.getABC().nsValueToName(abc.constants.getNamespace(m.namespace_index).getName(abc.constants, true)); - if (nsname == null) { - break; - } - if (nsname.contains(".")) { - nsname = nsname.substring(nsname.lastIndexOf('.') + 1); - } - if (!nsname.isEmpty()) { - break; - } - } - } - Namespace ns = m.getNamespace(abc.constants); - - if (nsname.contains(":")) { - nsname = ""; - } - - if ((!nsname.isEmpty()) && (!nsname.equals("-"))) { - } else { - if (ns != null) { - if (ns.kind == Namespace.KIND_NAMESPACE) { - nsname = ns.getName(abc.constants, true); - } - } - } - - if (nsname != null && (!nsname.contains(":")) && (!nsname.isEmpty())) { - ret += " " + nsname; - } - if (ns != null) { - ret += " " + ns.getPrefix(abc); - } - } - if (isStatic) { - if ((this instanceof TraitSlotConst) && ((TraitSlotConst) this).isNamespace()) { - //static is automatic - } else { - ret += " static"; - } - } - if ((kindFlags & ATTR_Final) > 0) { - if (!isStatic) { - ret += " final"; - } - } - return ret.trim(); - } - - @Override - public String toString() { - return "name_index=" + name_index + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); - } - - public String toString(ABC abc, List fullyQualifiedNames) { - return abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); - } - - public GraphTextWriter toString(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - writer.appendNoHilight(abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata)); - return writer; - } - - public void convert(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - } - - public GraphTextWriter toStringPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - String nsname = ns.getName(abc.constants, false); - writer.appendNoHilight("package"); - if (!nsname.isEmpty()) { - writer.appendNoHilight(" " + nsname); //assume not null name - } - writer.startBlock(); - toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - writer.endBlock(); - writer.newLine(); - } - return writer; - } - - public void convertPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - String nsname = ns.getName(abc.constants, false); - convert(parent, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } - } - - public GraphTextWriter toStringHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - return writer; - } - - public void convertHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - convert(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } - - public Multiname getName(ABC abc) { - if (name_index == 0) { - return null; - } else { - return abc.constants.getMultiname(name_index); - } - } - - public abstract int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) throws InterruptedException; - - public ClassPath getPath(ABC abc) { - Multiname name = getName(abc); - Namespace ns = name.getNamespace(abc.constants); - String packageName = ns.getName(abc.constants, false); - String objectName = name.getName(abc.constants, new ArrayList(), false); - return new ClassPath(packageName, objectName); //assume not null name - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.types.traits; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ClassPath; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.helpers.Helper; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public abstract class Trait implements Serializable { + + private static final int[] EMPTY_METADATA_ARRAY = new int[0]; + + public int name_index; + + public int kindType; + + public int kindFlags; + + public int[] metadata = EMPTY_METADATA_ARRAY; + + public long fileOffset; + + public byte[] bytes; + + public static final int ATTR_Final = 0x1; + + public static final int ATTR_Override = 0x2; + + public static final int ATTR_Metadata = 0x4; + + public static final int TRAIT_SLOT = 0; + + public static final int TRAIT_METHOD = 1; + + public static final int TRAIT_GETTER = 2; + + public static final int TRAIT_SETTER = 3; + + public static final int TRAIT_CLASS = 4; + + public static final int TRAIT_FUNCTION = 5; + + public static final int TRAIT_CONST = 6; + + public abstract void delete(ABC abc, boolean d); + + public String getModifiers(ABC abc, boolean isStatic) { + String ret = ""; + if ((kindFlags & ATTR_Override) > 0) { + ret += "override"; + } + Multiname m = getName(abc); + if (m != null) { + String nsname = ""; + //if (abc.constants.getNamespace(m.namespace_index).kind == Namespace.KIND_NAMESPACE) { + { + for (ABCContainerTag abcTag : abc.getAbcTags()) { + if (m.namespace_index == -1) { + break; + } + nsname = abcTag.getABC().nsValueToName(abc.constants.getNamespace(m.namespace_index).getName(abc.constants, true)).toString(); + if (nsname == null) { + break; + } + if (nsname.contains(".")) { + nsname = nsname.substring(nsname.lastIndexOf('.') + 1); + } + if (!nsname.isEmpty()) { + break; + } + } + } + Namespace ns = m.getNamespace(abc.constants); + + if (nsname.contains(":")) { + nsname = ""; + } + + if ((!nsname.isEmpty()) && (!nsname.equals("-"))) { + } else { + if (ns != null) { + if (ns.kind == Namespace.KIND_NAMESPACE) { + nsname = ns.getName(abc.constants, true); + } + } + } + + if (nsname != null && (!nsname.contains(":")) && (!nsname.isEmpty())) { + ret += " " + nsname; + } + if (ns != null) { + ret += " " + ns.getPrefix(abc); + } + } + if (isStatic) { + if ((this instanceof TraitSlotConst) && ((TraitSlotConst) this).isNamespace()) { + //static is automatic + } else { + ret += " static"; + } + } + if ((kindFlags & ATTR_Final) > 0) { + if (!isStatic) { + ret += " final"; + } + } + return ret.trim(); + } + + @Override + public String toString() { + return "name_index=" + name_index + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); + } + + public String toString(ABC abc, List fullyQualifiedNames) { + return abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); + } + + public GraphTextWriter toString(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + writer.appendNoHilight(abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata)); + return writer; + } + + public void convert(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + } + + public GraphTextWriter toStringPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + String nsname = ns.getName(abc.constants, false); + writer.appendNoHilight("package"); + if (!nsname.isEmpty()) { + writer.appendNoHilight(" " + nsname); //assume not null name + } + writer.startBlock(); + toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + writer.endBlock(); + writer.newLine(); + } + return writer; + } + + public void convertPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + String nsname = ns.getName(abc.constants, false); + convert(parent, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } + } + + public GraphTextWriter toStringHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + return writer; + } + + public void convertHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + convert(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } + + public Multiname getName(ABC abc) { + if (name_index == 0) { + return null; + } else { + return abc.constants.getMultiname(name_index); + } + } + + public abstract int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) throws InterruptedException; + + public ClassPath getPath(ABC abc) { + Multiname name = getName(abc); + Namespace ns = name.getNamespace(abc.constants); + String packageName = ns.getName(abc.constants, false); + String objectName = name.getName(abc.constants, new ArrayList(), false); + return new ClassPath(packageName, objectName); //assume not null name + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 19599b0fc..f1a51b1c5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -37,6 +37,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.helpers.Helper; import java.util.ArrayList; @@ -90,57 +91,53 @@ public class TraitClass extends Trait implements TraitWithSlot { return "Class " + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " slot=" + slot_id + " class_info=" + class_info + " metadata=" + Helper.intArrToString(metadata); } - private boolean parseUsagesFromNS(ABC abc, List imports, List uses, int namespace_index, String ignorePackage, String name) { + private boolean parseUsagesFromNS(ABC abc, List imports, List uses, int namespace_index, String ignorePackage, String name) { Namespace ns = abc.constants.getNamespace(namespace_index); if (name.isEmpty()) { name = "*"; } - String newimport = ns.getName(abc.constants, ns.kind == Namespace.KIND_NAMESPACE); + String nsname = ns.getName(abc.constants, ns.kind == Namespace.KIND_NAMESPACE); + DottedChain newimport = nsname == null ? new DottedChain() : new DottedChain(nsname.split("\\.")); /*if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_NAMESPACE) && (ns.kind != Namespace.KIND_STATIC_PROTECTED)) { return false; }*/ /*if (ns.kind == Namespace.KIND_NAMESPACE)*/ { - String oldimport = newimport; - newimport = null; + DottedChain oldimport = newimport; + newimport = new DottedChain(); for (ABCContainerTag abcTag : abc.getAbcTags()) { - String newname = abcTag.getABC().nsValueToName(oldimport); - if (newname.equals("-")) { + DottedChain newname = abcTag.getABC().nsValueToName(oldimport == null ? null : oldimport.toString()); + if (newname.toString().equals("-")) { return true; } - if (!newname.isEmpty()) { + if (!newname.toString().isEmpty()) { newimport = newname; break; } } - if (newimport == null) { + if (newimport.parts.isEmpty()) { newimport = oldimport; - newimport += "." + name; + newimport.parts.add(name); } - if (newimport != null && newimport.isEmpty()) { - newimport = null; + if (!newimport.parts.isEmpty() && newimport.toString().isEmpty()) { + newimport.parts.clear(); } - if (newimport != null) { + if (newimport.parts.isEmpty()) { /* if(ns.kind==Namespace.KIND_PACKAGE){ newimport+=".*"; }*/ if (!imports.contains(newimport)) { - if (newimport.contains(":")) { - return true; - } - String pkg = ""; - if (newimport.contains(".")) { - pkg = newimport.substring(0, newimport.lastIndexOf('.')); - } - String usname = newimport; - if (usname.contains(".")) { - usname = usname.substring(usname.lastIndexOf('.') + 1); - } + //?? + /*if (newimport.contains(":")) { + return true; + }*/ + DottedChain pkg = newimport.getWithoutLast(); + String usname = newimport.getLast(); if (ns.kind == Namespace.KIND_PACKAGE) { if (!pkg.equals(ignorePackage)) { - if (!pkg.equals("__AS3__.vec")) { //Automatic import + if (!pkg.toString().equals("__AS3__.vec")) { //Automatic import imports.add(newimport); } } @@ -162,38 +159,39 @@ public class TraitClass extends Trait implements TraitWithSlot { return false; } - private void parseImportsUsagesFromNS(ABC abc, List imports, List uses, int namespace_index, String ignorePackage, String name) { + private void parseImportsUsagesFromNS(ABC abc, List imports, List uses, int namespace_index, String ignorePackage, String name) { Namespace ns = abc.constants.getNamespace(namespace_index); if (name.isEmpty()) { name = "*"; } - String newimport = ns.getName(abc.constants, false); + String niS = ns.getName(abc.constants, false); + DottedChain newimport = niS == null ? new DottedChain() : new DottedChain(niS.split("\\.")); if (parseUsagesFromNS(abc, imports, uses, namespace_index, ignorePackage, name)) { return; } else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { return; } - if (newimport == null) { - newimport = ""; - } - //if (!newimport.equals("")) { - newimport += "." + name; - if (newimport.contains(":")) { - return; + if (newimport.parts.isEmpty()) { + newimport = new DottedChain(""); } + newimport.parts.add(name); + //WUT? + /*if (newimport.contains(":")) { + return; + }*/ if (!imports.contains(newimport)) { - String pkg = newimport.substring(0, newimport.lastIndexOf('.')); - if (pkg.equals("__AS3__.vec")) { //special case - is imported always + DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.')); + if (pkg.toString().equals("__AS3__.vec")) { //special case - is imported always return; } - if (!pkg.equals(ignorePackage)) { + if (!pkg.toString().equals(ignorePackage)) { imports.add(newimport); } } //} } - private void parseUsagesFromMultiname(ABC abc, List imports, List uses, Multiname m, String ignorePackage, List fullyQualifiedNames) { + private void parseUsagesFromMultiname(ABC abc, List imports, List uses, Multiname m, String ignorePackage, List fullyQualifiedNames) { if (m != null) { if (m.kind == Multiname.TYPENAME) { if (m.qname_index != 0) { @@ -224,7 +222,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - private void parseImportsUsagesFromMultiname(ABC abc, List imports, List uses, Multiname m, String ignorePackage, List fullyQualifiedNames) { + private void parseImportsUsagesFromMultiname(ABC abc, List imports, List uses, Multiname m, String ignorePackage, List fullyQualifiedNames) { if (m != null) { if (m.kind == Multiname.TYPENAME) { if (m.qname_index != 0) { @@ -251,7 +249,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - private void parseImportsUsagesFromMethodInfo(ABC abc, int method_index, List imports, List uses, String ignorePackage, List fullyQualifiedNames, List visitedMethods) { + private void parseImportsUsagesFromMethodInfo(ABC abc, int method_index, List imports, List uses, String ignorePackage, List fullyQualifiedNames, List visitedMethods) { if ((method_index < 0) || (method_index >= abc.method_info.size())) { return; } @@ -272,7 +270,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } for (AVM2Instruction ins : body.getCode().code) { if (ins.definition instanceof AlchemyTypeIns) { - String nimport = AlchemyTypeIns.ALCHEMY_PACKAGE + "." + ins.definition.instructionName; + DottedChain nimport = new DottedChain((AlchemyTypeIns.ALCHEMY_PACKAGE + "." + ins.definition.instructionName).split("\\.")); if (!imports.contains(nimport)) { imports.add(nimport); } @@ -306,13 +304,13 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - private void parseImportsUsagesFromTraits(ABC abc, Traits ts, List imports, List uses, String ignorePackage, List fullyQualifiedNames) { + private void parseImportsUsagesFromTraits(ABC abc, Traits ts, List imports, List uses, String ignorePackage, List fullyQualifiedNames) { for (Trait t : ts.traits) { parseImportsUsagesFromTrait(abc, t, imports, uses, ignorePackage, fullyQualifiedNames); } } - private void parseImportsUsagesFromTrait(ABC abc, Trait t, List imports, List uses, String ignorePackage, List fullyQualifiedNames) { + private void parseImportsUsagesFromTrait(ABC abc, Trait t, List imports, List uses, String ignorePackage, List fullyQualifiedNames) { if (t instanceof TraitMethodGetterSetter) { TraitMethodGetterSetter tm = (TraitMethodGetterSetter) t; parseImportsUsagesFromMultiname(abc, imports, uses, abc.constants.getMultiname(tm.name_index), ignorePackage, fullyQualifiedNames); @@ -328,7 +326,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - private List getImportsUsages(ABC abc, List imports, List uses, List fullyQualifiedNames) { + private List getImportsUsages(ABC abc, List imports, List uses, List fullyQualifiedNames) { //constructor String packageName = abc.instance_info.get(class_info).getName(abc.constants).getNamespace(abc.constants).getName(abc.constants, false); //assume not null name @@ -384,7 +382,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } //imports - List imports = new ArrayList<>(); + List imports = new ArrayList<>(); List uses = new ArrayList<>(); getImportsUsages(abc, imports, uses, new ArrayList()); @@ -392,20 +390,16 @@ public class TraitClass extends Trait implements TraitWithSlot { List importnames = new ArrayList<>(); importnames.addAll(namesInThisPackage); - for (String ipath : imports) { - String name = ipath; - String pkg = ""; - if (name.contains(".")) { - pkg = name.substring(0, name.lastIndexOf('.')); - name = name.substring(name.lastIndexOf('.') + 1); - } - if (importnames.contains(name) || ((!pkg.isEmpty()) && isBuiltInClass(name))) { + for (DottedChain ipath : imports) { + String name = ipath.getLast(); + DottedChain pkg = ipath.getWithoutLast(); + if (importnames.contains(name) || ((!pkg.toString().isEmpty()) && isBuiltInClass(name))) { fullyQualifiedNames.add(name); } else { importnames.add(name); } } - /*List imports2 = new ArrayList(); + /*List imports2 = new ArrayList(); for (String path : imports) { String name = path; String pkg = ""; @@ -421,21 +415,23 @@ public class TraitClass extends Trait implements TraitWithSlot { imports = imports2;*/ for (int i = 0; i < imports.size(); i++) { - String imp = imports.get(i); - String pkg = imp.substring(0, imp.lastIndexOf('.')); - String name = imp.substring(imp.lastIndexOf('.') + 1); + DottedChain imp = imports.get(i); + DottedChain pkg = imp.getWithoutLast(); //imp.substring(0, imp.lastIndexOf('.')); + String name = imp.getLast();//imp.substring(imp.lastIndexOf('.') + 1); if (name.equals("*")) { continue; } - if (imports.contains(pkg + ".*")) { + DottedChain dAll = new DottedChain(pkg.parts); + dAll.parts.add("*"); + if (imports.contains(dAll)) { imports.remove(i); i--; } } boolean hasImport = false; - for (String imp : imports) { - if (!imp.startsWith(".")) { + for (DottedChain imp : imports) { + if (!imp.parts.get(0).isEmpty()) { //No imports from root package writer.appendNoHilight("import " + imp + ";").newLine(); hasImport = true; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ClassNameMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ClassNameMultinameUsage.java index a755f3e8e..56f98f9a9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ClassNameMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ClassNameMultinameUsage.java @@ -30,6 +30,6 @@ public class ClassNameMultinameUsage extends InsideClassMultinameUsage implement @Override public String toString() { - return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants, false); + return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants).toPrintableString(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/InsideClassMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/InsideClassMultinameUsage.java index ea1c31796..6244374aa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/InsideClassMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/InsideClassMultinameUsage.java @@ -36,7 +36,7 @@ public abstract class InsideClassMultinameUsage extends MultinameUsage { @Override public String toString() { - return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants, false); + return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants).toPrintableString(); } public int getMultinameIndex() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 1d770a11b..2a7ae08f1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -455,7 +455,9 @@ public class Configuration { @ConfigurationCategory("ui") public static final ConfigurationItem saveSessionOnExit = null; - public static final ConfigurationItem lastSessionData = null; + public static final ConfigurationItem lastSessionFiles = null; + + public static final ConfigurationItem lastSessionSelection = null; @ConfigurationDefaultBoolean(true) @ConfigurationCategory("ui") diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java new file mode 100644 index 000000000..b6066cc43 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph; + +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * + * @author JPEXS + */ +public class DottedChain { + + public List parts = new ArrayList<>(); + + public DottedChain(List parts) { + this.parts = new ArrayList<>(parts); + } + + public DottedChain(String... parts) { + for (int i = 0; i < parts.length; i++) { + this.parts.add(parts[i]); + } + } + + public String getLast() { + if (parts.isEmpty()) { + return ""; + } else { + return parts.get(parts.size() - 1); + } + } + + public DottedChain getWithoutLast() { + List nparts = new ArrayList<>(parts); + if (!nparts.isEmpty()) { + nparts.remove(nparts.size() - 1); + } + return new DottedChain(nparts); + } + + public String toPrintableString() { + String ret = ""; + for (int i = 0; i < parts.size(); i++) { + if (i > 0) { + ret += "."; + } + ret += IdentifiersDeobfuscation.printIdentifier(true, parts.get(0)); + } + return ret; + } + + @Override + public String toString() { + String ret = ""; + for (int i = 0; i < parts.size(); i++) { + if (i > 0) { + ret += "."; + } + ret += parts.get(i); + } + return ret; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 89 * hash + Objects.hashCode(this.parts); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof String) { + obj = new DottedChain(((String) obj).split("\\.")); + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final DottedChain other = (DottedChain) obj; + if (!Objects.equals(this.parts, other.parts)) { + return false; + } + return true; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java index ad27e56ea..9dc3bc898 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java @@ -31,33 +31,37 @@ import java.util.Objects; * @author JPEXS */ public class TypeItem extends GraphTargetItem { - + public static TypeItem BOOLEAN = new TypeItem("Boolean"); - + public static TypeItem STRING = new TypeItem("String"); - + public static TypeItem ARRAY = new TypeItem("Array"); - + public static UnboundedTypeItem UNBOUNDED = new UnboundedTypeItem(); - - public String fullTypeName; - - public TypeItem(String fullTypeName) { + + public DottedChain fullTypeName; + + public TypeItem(String s) { + this(s == null ? new DottedChain() : new DottedChain(s.split("\\."))); + } + + public TypeItem(DottedChain fullTypeName) { this(fullTypeName, new ArrayList()); } - - public TypeItem(String fullTypeName, List subtypes) { + + public TypeItem(DottedChain fullTypeName, List subtypes) { super(null, NOPRECEDENCE); this.fullTypeName = fullTypeName; } - + @Override public int hashCode() { int hash = 7; hash = 83 * hash + Objects.hashCode(this.fullTypeName); return hash; } - + @Override public boolean equals(Object obj) { if (obj == null) { @@ -72,37 +76,33 @@ public class TypeItem extends GraphTargetItem { } return true; } - + @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { if (localData.fullyQualifiedNames.contains(fullTypeName)) { - writer.hilightSpecial(IdentifiersDeobfuscation.printNamespace(localData.constantsAvm2 != null, fullTypeName), HighlightSpecialType.TYPE_NAME, fullTypeName); + writer.hilightSpecial(IdentifiersDeobfuscation.printNamespace(localData.constantsAvm2 != null, fullTypeName.toPrintableString()), HighlightSpecialType.TYPE_NAME, fullTypeName.toPrintableString()); } else { - String simpleName = fullTypeName; - if (simpleName.contains(".")) { - simpleName = simpleName.substring(simpleName.lastIndexOf('.') + 1); - } - writer.hilightSpecial(IdentifiersDeobfuscation.printNamespace(localData.constantsAvm2 != null, simpleName), HighlightSpecialType.TYPE_NAME, fullTypeName); + writer.hilightSpecial(IdentifiersDeobfuscation.printIdentifier(localData.constantsAvm2 != null, fullTypeName.getLast()), HighlightSpecialType.TYPE_NAME, fullTypeName.toPrintableString()); } - + return writer; } - + @Override public GraphTargetItem returnType() { return this; } - + @Override public boolean hasReturnValue() { return true; } - + @Override public String toString() { - return fullTypeName; + return fullTypeName.toString(); } - + @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return generator.generate(localData, this); diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/Helper.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/Helper.java index 0b2218c72..a485bd40a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/helpers/Helper.java +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/Helper.java @@ -1,1328 +1,1343 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.helpers; - -import com.jpexs.decompiler.flash.AppResources; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.helpers.Freed; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.Component; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.Area; -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferInt; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.xml.bind.DatatypeConverter; - -/** - * Class with helper method - * - * @author JPEXS, Paolo Cancedda - */ -public class Helper { - - public static String newLine = System.getProperty("line.separator"); - - public static String hexData = "#hexdata"; - - public static String constants = "#constants"; - - public static String decompilationErrorAdd = null; - - private static final Map shapeCache = new HashMap<>(); - - private static final String[] hexStringCache; - - static { - hexStringCache = new String[256]; - for (int i = 0; i < hexStringCache.length; i++) { - hexStringCache[i] = String.format("%02x", i); - } - } - - /** - * Converts array of int values to string - * - * @param array Array of int values - * @return String representation of the array - */ - public static String intArrToString(int[] array) { - StringBuilder sb = new StringBuilder(); - intArrToStringBuilder(array, sb); - return sb.toString(); - } - - public static void intArrToStringBuilder(int[] array, StringBuilder sb) { - sb.append("["); - for (int i = 0; i < array.length; i++) { - if (i > 0) { - sb.append(","); - } - sb.append(array[i]); - } - sb.append("]"); - } - - /** - * Converts array of byte values to string - * - * @param array Array of byte values - * @return String representation of the array - */ - public static String byteArrToString(byte[] array) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - for (int i = 0; i < array.length; i++) { - if (i > 0) { - sb.append(" "); - } - sb.append(hexStringCache[array[i] & 0xff]); - } - sb.append("]"); - return sb.toString(); - } - - /** - * Adds zeros to beginning of the number to fill specified length. Returns - * as string - * - * @param number Number as string - * @param length Length of new string - * @return Number with added zeros - */ - public static String padZeros(String number, int length) { - int count = length - number.length(); - for (int i = 0; i < count; i++) { - number = "0" + number; - } - return number; - } - - /** - * Formats specified address to four numbers xxxx - * (or five numbers when showing decimal addresses) - * - * @param number Address to format - * @return String representation of the address - */ - public static String formatAddress(long number) { - return formatAddress(number, Configuration.decimalAddress.get()); - } - - /** - * Formats specified address to four numbers xxxx - * (or five numbers when showing decimal addresses) - * - * @param number Address to format - * @param decimal Use decimal format - * @return String representation of the address - */ - public static String formatAddress(long number, boolean decimal) { - if (decimal) { - return String.format("%05d", number); - } - return String.format("%04x", number); - } - - /** - * Escapes string by adding backslashes - * - * @param s String to escape - * @return Escaped string - */ - public static String escapeString(String s) { - StringBuilder ret = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '\n') { - ret.append("\\n"); - } else if (c == '\r') { - ret.append("\\r"); - } else if (c == '\t') { - ret.append("\\t"); - } else if (c == '\b') { - ret.append("\\b"); - } else if (c == '\f') { - ret.append("\\f"); - } else if (c == '\\') { - ret.append("\\\\"); - } else if (c < 32) { - ret.append("\\x").append(byteToHex((byte) c)); - } else { - ret.append(c); - } - } - - return ret.toString(); - } - - /** - * Escapes string by adding backslashes - * - * @param s String to escape - * @return Escaped string - */ - public static String escapeActionScriptString(String s) { - StringBuilder ret = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '\n') { - ret.append("\\n"); - } else if (c == '\r') { - ret.append("\\r"); - } else if (c == '\t') { - ret.append("\\t"); - } else if (c == '\b') { - ret.append("\\b"); - } else if (c == '\f') { - ret.append("\\f"); - } else if (c == '\\') { - ret.append("\\\\"); - } else if (c == '"') { - ret.append("\\\""); - } else if (c == '\'') { - ret.append("\\'"); - } else if (c < 32) { - ret.append("\\x").append(byteToHex((byte) c)); - } else { - ret.append(c); - } - } - - return ret.toString(); - } - - /** - * Escapes string by adding backslashes - * - * @param s String to escape - * @return Escaped string - */ - public static String escapeJavaString(String s) { - StringBuilder ret = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '\n') { - ret.append("\\n"); - } else if (c == '\r') { - ret.append("\\r"); - } else if (c == '\t') { - ret.append("\\t"); - } else if (c == '\b') { - ret.append("\\b"); - } else if (c == '\f') { - ret.append("\\f"); - } else if (c == '\\') { - ret.append("\\\\"); - } else if (c == '"') { - ret.append("\\\""); - } else if (c < 32) { - // \\x is not available in Java string, we should use \\u instead - ret.append("\\u00").append(byteToHex((byte) c)); - } else { - ret.append(c); - } - } - - return ret.toString(); - } - - /** - * Unescapes a string that contains standard Java escape sequences. - *
    - *
  • \b \f \n \r \t \" \' : - * BS, FF, NL, CR, TAB, double and single quote.
  • - *
  • \X \XX \XXX : Octal character - * specification (0 - 377, 0x00 - 0xFF).
  • - *
  • \uXXXX : Hexadecimal based Unicode - * character.
  • - *
- * - * @param st - * A string optionally containing standard java escape sequences. - * @return The translated string. - */ - public static String unescapeJavaString(String st) { - - StringBuilder sb = new StringBuilder(st.length()); - - for (int i = 0; i < st.length(); i++) { - char ch = st.charAt(i); - if (ch == '\\') { - char nextChar = (i == st.length() - 1) ? '\\' : st - .charAt(i + 1); - // Octal escape? - if (nextChar >= '0' && nextChar <= '7') { - String code = "" + nextChar; - i++; - if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' - && st.charAt(i + 1) <= '7') { - code += st.charAt(i + 1); - i++; - if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' - && st.charAt(i + 1) <= '7') { - code += st.charAt(i + 1); - i++; - } - } - sb.append((char) Integer.parseInt(code, 8)); - continue; - } - - switch (nextChar) { - case '\\': - ch = '\\'; - break; - case 'b': - ch = '\b'; - break; - case 'f': - ch = '\f'; - break; - case 'n': - ch = '\n'; - break; - case 'r': - ch = '\r'; - break; - case 't': - ch = '\t'; - break; - case '\"': - ch = '\"'; - break; - case '\'': - ch = '\''; - break; - // Hex Unicode: u???? - case 'u': - if (i >= st.length() - 5) { - ch = 'u'; - break; - } - int code = Integer.parseInt( - "" + st.charAt(i + 2) + st.charAt(i + 3) - + st.charAt(i + 4) + st.charAt(i + 5), 16); - sb.append(Character.toChars(code)); - i += 5; - continue; - } - - i++; - } - - sb.append(ch); - } - - return sb.toString(); - } - - public static String getValidHtmlId(String text) { - // ID and NAME tokens must begin with a letter ([A-Za-z]) and - // may be followed by any number of letters, digits ([0-9]), - // hyphens ("-"), underscores ("_"), colons (":"), and periods ("."). - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if ((ch >= 'a' && ch <= 'z') - || (ch >= 'A' && ch <= 'Z') - || (i > 0 && ((ch >= '0' && ch <= '9') - || ch == '-' || ch == '_' || ch == ':' || ch == '.'))) { - sb.append(ch); - } else { - sb.append('_'); - } - } - return sb.toString(); - } - - private final static String SPACES12 = " "; - - private final static String ZEROS8 = "00000000"; - - public static String formatHex(int value, int width) { - StringBuilder sb = new StringBuilder(); - sb.append(Integer.toHexString(value)); - if (width > sb.length()) { - sb.insert(0, ZEROS8, 0, width - sb.length()); - } - return sb.toString(); - } - - public static String formatInt(int value, int width) { - StringBuilder sb = new StringBuilder(); - sb.append(value); - if (width > sb.length()) { - sb.insert(0, SPACES12, 0, width - sb.length()); - } - return sb.toString(); - } - - public static String indent(int level, String ss, String indentStr) { - StringBuilder sb = new StringBuilder(); - for (int ii = 0; ii < level; ii++) { - sb.append(indentStr); - } - sb.append(ss); - return sb.toString(); - } - - public static String indentRows(int level, String ss, String indentStr) { - StringBuilder sb = new StringBuilder(); - for (int ii = 0; ii < level; ii++) { - sb.append(indentStr); - } - ss = ss.replaceAll("(\r\n|\r|\n)", "\r\n"); - ss = "\r\n" + ss; - String repl = "\r\n" + sb.toString(); - ss = ss.replace("\r\n", repl); - if (ss.endsWith(repl)) { - ss = ss.substring(0, ss.length() - sb.toString().length()); - } - ss = ss.substring(2); - return ss; - } - - public static String unindentRows(int prefixLineCount, int level, String text) { - StringBuilder sb = new StringBuilder(); - Scanner scanner = new Scanner(text); - String indentStr = ""; - for (int i = 0; i < level; i++) { - indentStr += Configuration.getCodeFormatting().indentString; - } - int indentLength = indentStr.length(); - for (int i = 0; i < prefixLineCount; i++) { - scanner.nextLine(); // ignore line - } - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (line.startsWith(indentStr)) { - sb.append(line.substring(indentLength)).append(Configuration.getCodeFormatting().newLineChars); - } else { - return sb.toString(); - } - } - return sb.toString(); - } - - public static int getLineCount(String s) { - if (s.endsWith("\r\n")) { - s = s.substring(0, s.length() - 2); - } else if (s.endsWith("\r")) { - s = s.substring(0, s.length() - 1); - } else if (s.endsWith("\n")) { - s = s.substring(0, s.length() - 1); - } - String[] parts = s.split("(\r\n|\r|\n)"); - return parts.length; - } - - public static String padZeros(long number, int length) { - String ret = Long.toString(number); - while (ret.length() < length) { - ret = "0" + ret; - } - return ret; - } - - public static String byteToHex(byte b) { - return hexStringCache[b & 0xff]; - } - - public static String byteArrayToHex(byte[] data) { - StringBuilder sb = new StringBuilder(data.length * 2); - for (byte b : data) { - sb.append(hexStringCache[b & 0xff]); - } - - return sb.toString(); - } - - public static String bytesToHexString(byte[] bytes) { - return bytesToHexString(bytes, 0); - } - - public static String bytesToHexString(byte[] bytes, int start) { - StringBuilder sb = new StringBuilder(); - if (start < bytes.length) { - for (int ii = start; ii < bytes.length; ii++) { - sb.append(formatHex(bytes[ii] & 0xff, 2)); - sb.append(' '); - } - sb.setLength(sb.length() - 1); - } - return sb.toString(); - } - - public static String bytesToHexString(int maxByteCountInString, byte[] bytes, int start) { - if (bytes.length - start <= maxByteCountInString) { - return bytesToHexString(bytes, start); - } - byte[] trailingBytes = new byte[maxByteCountInString / 2]; - byte[] headingBytes = new byte[maxByteCountInString - trailingBytes.length]; - System.arraycopy(bytes, start, headingBytes, 0, headingBytes.length); - int startOfTrailingBytes = bytes.length - trailingBytes.length; - System.arraycopy(bytes, startOfTrailingBytes, trailingBytes, 0, trailingBytes.length); - StringBuilder sb = new StringBuilder(); - sb.append(bytesToHexString(headingBytes, 0)); - if (trailingBytes.length > 0) { - sb.append(" ... "); - sb.append(bytesToHexString(trailingBytes, 0)); - } - return sb.toString(); - } - - public static String format(String str, int len) { - if (len <= str.length()) { - return str; - } - StringBuilder sb = new StringBuilder(str); - for (int ii = str.length(); ii < len; ii++) { - sb.append(' '); - } - return sb.toString(); - } - - public static String joinStrings(Iterable arr, String glue) { - StringBuilder ret = new StringBuilder(); - boolean first = true; - for (Object s : arr) { - if (!first) { - ret.append(glue); - } else { - first = false; - } - ret.append(s); - } - return ret.toString(); - } - - public static String joinStrings(String[] arr, String glue) { - StringBuilder ret = new StringBuilder(); - boolean first = true; - for (String s : arr) { - if (!first) { - ret.append(glue); - } else { - first = false; - } - ret.append(s); - } - return ret.toString(); - } - - public static String joinStrings(List arr, String formatString, String glue) { - StringBuilder ret = new StringBuilder(); - boolean first = true; - for (String s : arr) { - if (!first) { - ret.append(glue); - } else { - first = false; - } - ret.append(String.format(formatString, s)); - } - return ret.toString(); - } - - public static String joinStrings(String[] arr, String formatString, String glue) { - StringBuilder ret = new StringBuilder(); - boolean first = true; - for (String s : arr) { - if (!first) { - ret.append(glue); - } else { - first = false; - } - ret.append(String.format(formatString, s)); - } - return ret.toString(); - } - - @SuppressWarnings("unchecked") - public static E deepCopy(E o) { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { - oos.writeObject(o); - oos.flush(); - } - E copy; - try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { - copy = (E) ois.readObject(); - } - return copy; - } catch (IOException | ClassNotFoundException ex) { - Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, "Copy error", ex); - return null; - } - } - - public static List toList(Object... rest) { - List ret = new ArrayList<>(); - ret.addAll(Arrays.asList(rest)); - return ret; - } - - public static ByteArrayInputStream getInputStream(byte[]... data) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - try { - for (byte[] d : data) { - baos.write(d); - } - } catch (IOException iex) { - } - return new ByteArrayInputStream(baos.toByteArray()); - } - - public static byte[] readFile(String... file) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - for (String f : file) { - try (FileInputStream fis = new FileInputStream(f)) { - byte[] buf = new byte[4096]; - int cnt = 0; - while ((cnt = fis.read(buf)) > 0) { - baos.write(buf, 0, cnt); - } - } catch (IOException ex) { - Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); - } - } - return baos.toByteArray(); - } - - public static String readTextFile(String... file) { - byte[] data = readFile(file); - if (data.length > 1 && data[0] == (byte) 0xef && data[1] == (byte) 0xbb && data[2] == (byte) 0xbf) { - // remove UTF-8 BOM - return new String(data, 3, data.length - 3, Utf8Helper.charset); - } - - return new String(data, Utf8Helper.charset); - } - - public static byte[] readStream(InputStream is) { - if (is instanceof MemoryInputStream) { - return ((MemoryInputStream) is).getAllRead(); - } - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - copyStream(is, baos, Long.MAX_VALUE); - return baos.toByteArray(); - } - - public static void copyStream(InputStream is, OutputStream os, long maxLength) { - try { - final int bufSize = 4096; - byte[] buf = new byte[bufSize]; - int cnt = 0; - while ((cnt = is.read(buf)) > 0) { - os.write(buf, 0, cnt); - maxLength -= cnt; - - // last chunk is smaller - if (maxLength < bufSize) { - buf = new byte[(int) maxLength]; - } - } - } catch (IOException ex) { - // ignore - } - } - - public static void writeFile(String file, byte[]... data) { - try (FileOutputStream fos = new FileOutputStream(file)) { - for (byte[] d : data) { - fos.write(d); - } - } catch (IOException ex) { - // ignore - } - } - - public static String stackToString(TranslateStack stack, LocalData localData) throws InterruptedException { - String ret = "["; - for (int i = stack.size() - 1; i >= 0; i--) { - if (i < stack.size() - 1) { - ret += ", "; - } - ret += stack.get(i).toString(localData); - } - ret += "]"; - return ret; - } - - public static File fixDialogFile(File f) { - Pattern pat = Pattern.compile("\"([^\"]+)\""); - String name = f.getAbsolutePath(); - Matcher m = pat.matcher(name); - if (m.find()) { - f = new File(m.group(1)); - } - return f; - } - - private static final BitSet fileNameInvalidChars; - - private static final List invalidFilenamesParts; - - static { - BitSet toEncode = new BitSet(256); - - for (int i = 0; i < 32; i++) { - toEncode.set(i); - } - - toEncode.set('\\'); - toEncode.set('/'); - toEncode.set(':'); - toEncode.set('*'); - toEncode.set('?'); - toEncode.set('"'); - toEncode.set('<'); - toEncode.set('>'); - toEncode.set('|'); - - fileNameInvalidChars = toEncode; - - //windows reserved filenames: - invalidFilenamesParts = new ArrayList<>(); - invalidFilenamesParts.add("CON"); - invalidFilenamesParts.add("PRN"); - invalidFilenamesParts.add("AUX"); - invalidFilenamesParts.add("CLOCK$"); - invalidFilenamesParts.add("NUL"); - for (int i = 1; i <= 9; i++) { - invalidFilenamesParts.add("COM" + i); - invalidFilenamesParts.add("LPT" + i); - } - } - - public static String makeFileName(String str) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < str.length(); i++) { - int ch = (int) str.charAt(i); - if (ch < 256 && fileNameInvalidChars.get(ch)) { - sb.append("%").append(String.format("%02X", ch)); - } else { - sb.append((char) ch); - } - } - str = sb.toString(); - if (str.endsWith(" ")) { - str = str.substring(0, str.length() - 1) + "%20"; - } - if (str.endsWith(".")) { - str = str.substring(0, str.length() - 1) + "%2E"; - } - str = "." + str + "."; - for (String inv : invalidFilenamesParts) { - str = Pattern.compile("\\." + Pattern.quote(inv) + "\\.", Pattern.CASE_INSENSITIVE).matcher(str).replaceAll("._" + inv + "."); - } - str = str.substring(1, str.length() - 1); //remove dots - if (str.isEmpty()) { - str = "unnamed"; - } - return str; - } - - public static String strToHex(String s) { - byte[] bs = Utf8Helper.getBytes(s); - String sn = ""; - for (int i = 0; i < bs.length; i++) { - sn += "0x" + Integer.toHexString(bs[i] & 0xff) + " "; - } - return sn; - } - - public static void emptyObject(Object obj) { - Field[] fields = obj.getClass().getDeclaredFields(); - for (Field f : fields) { - if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC - || f.getType().isPrimitive()) { - continue; - } - try { - f.setAccessible(true); - - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); - - Object v = f.get(obj); - if (v != null) { - try { - if (v instanceof Collection) { - ((Collection) v).clear(); - } - if (v instanceof Component) { - if (((Component) v).getParent() != null) { - ((Component) v).getParent().remove((Component) v); - } - } - if (v instanceof Freed) { - Freed freed = ((Freed) v); - if (!freed.isFreeing()) { - ((Freed) v).free(); - } - } - } catch (Throwable t) { - } - - f.set(obj, null); - } - } catch (UnsupportedOperationException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException ex) { - throw new Error(ex); - } - } - } - - public static String formatTimeSec(long timeMs) { - long timeS = timeMs / 1000; - timeMs %= 1000; - long timeM = timeS / 60; - timeS %= 60; - long timeH = timeM / 60; - timeM %= 60; - String timeStr = ""; - if (timeH > 0) { - timeStr += Helper.padZeros(timeH, 2) + ":"; - } - timeStr += Helper.padZeros(timeM, 2) + ":"; - timeStr += Helper.padZeros(timeS, 2) + "." + Helper.padZeros(timeMs, 3); - return timeStr; - } - - public static String formatFileSize(long fileSizeLong) { - double fileSize = fileSizeLong; - if (fileSize < 1024) { - return String.format("%d bytes", fileSizeLong); - } - fileSize /= 1024; - if (fileSize < 1024) { - return String.format("%.2f KB", fileSize); - } - fileSize /= 1024; - return String.format("%.2f MB", fileSize); - } - - public static void freeMem() { - Cache.clearAll(); - System.gc(); - } - - public static String formatTimeToText(int timeS) { - long timeM = timeS / 60; - timeS %= 60; - long timeH = timeM / 60; - timeM %= 60; - - String timeStr = ""; - String strAnd = AppResources.translate("timeFormat.and"); - String strHour = AppResources.translate("timeFormat.hour"); - String strHours = AppResources.translate("timeFormat.hours"); - String strMinute = AppResources.translate("timeFormat.minute"); - String strMinutes = AppResources.translate("timeFormat.minutes"); - String strSecond = AppResources.translate("timeFormat.second"); - String strSeconds = AppResources.translate("timeFormat.seconds"); - - if (timeH > 0) { - timeStr += timeH + " " + (timeH > 1 ? strHours : strHour); - } - if (timeM > 0) { - if (timeStr.length() > 0) { - timeStr += " " + strAnd + " "; - } - timeStr += timeM + " " + (timeM > 1 ? strMinutes : strMinute); - } - if (timeS > 0) { - if (timeStr.length() > 0) { - timeStr += " " + strAnd + " "; - } - timeStr += timeS + " " + (timeS > 1 ? strSeconds : strSecond); - } - - // (currently) used only in log, so no localization is required - return timeStr; - } - - public static GraphTextWriter byteArrayToHexWithHeader(GraphTextWriter writer, byte[] data) { - writer.appendNoHilight("#hexdata").newLine().newLine(); - return byteArrayToHex(writer, data, 8, 8, false, false); - } - - public static GraphTextWriter byteArrayToHex(GraphTextWriter writer, byte[] data, int bytesPerRow, int groupSize, boolean addChars, boolean showAddress) { - - /* // hex data from decompiled actions - Scanner scanner = new Scanner(srcWithHex); - while (scanner.hasNextLine()) { - String line = scanner.nextLine().trim(); - if (line.startsWith(";")) { - result.append(line.substring(1).trim()).append(nl); - } else { - result.append(";").append(line).append(nl); - } - }*/ - int length = data.length; - - int rowCount = length / bytesPerRow; - if (length % bytesPerRow > 0) { - rowCount++; - } - - long address = 0; - for (int row = 0; row < rowCount; row++) { - if (row > 0) { - writer.newLine(); - } - - if (showAddress) { - writer.appendNoHilight("0x" + String.format("%08x ", address)); - } - - for (int i = 0; i < bytesPerRow; i++) { - int idx = row * bytesPerRow + i; - if (length > idx) { - if (i > 0 && i % groupSize == 0) { - writer.appendNoHilight(" "); - } - writer.appendNoHilight(byteToHex(data[idx])).appendNoHilight(" "); - } else { - if (addChars) { - if (i > 0 && i % groupSize == 0) { - writer.appendNoHilight(" "); - } - writer.appendNoHilight(" "); - } - } - address += bytesPerRow; - } - - if (addChars) { - writer.appendNoHilight(" "); - for (int i = 0; i < bytesPerRow; i++) { - int idx = row * bytesPerRow + i; - if (length == idx) { - break; - } - if (i > 0 && i % groupSize == 0) { - writer.appendNoHilight(" "); - } - byte ch = data[idx]; - if (ch >= 0 && ch < 32) { - ch = '.'; - } - writer.appendNoHilight((char) ch + ""); - } - } - } - - writer.newLine(); - return writer; - } - - public static byte[] getBytesFromHexaText(String text) { - Scanner scanner = new Scanner(text); - scanner.nextLine(); // ignore first line - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - while (scanner.hasNextLine()) { - String line = scanner.nextLine().trim(); - if (line.startsWith(";")) { - continue; - } - line = line.replace(" ", ""); - for (int i = 0; i < line.length() / 2; i++) { - String hexStr = line.substring(i * 2, (i + 1) * 2); - byte b = (byte) Integer.parseInt(hexStr, 16); - baos.write(b); - } - } - byte[] data = baos.toByteArray(); - return data; - } - - public static List> getConstantPoolsFromText(String text) { - Scanner scanner = new Scanner(text); - scanner.nextLine(); // ignore first line - List> result = new ArrayList<>(); - List cPool = new ArrayList<>(); - result.add(cPool); - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (line.startsWith("---")) { - cPool = new ArrayList<>(); - result.add(cPool); - } - - String[] parts = line.split("\\|", 2); - if (parts.length >= 2) { - cPool.add(unescapeJavaString(parts[1])); - } - } - - return result; - } - - public static boolean contains(int[] array, int value) { - if (array == null) { - return false; - } - - for (int i : array) { - if (i == value) { - return true; - } - } - return false; - } - - public static void saveStream(InputStream is, File output) throws IOException { - byte[] buf = new byte[4096]; - int cnt; - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(output))) { - while ((cnt = is.read(buf)) > 0) { - fos.write(buf, 0, cnt); - fos.flush(); - } - } - } - - public static String getDecompilationSkippedComment() { - return "// " + AppResources.translate("decompilation.skipped"); - } - - public static void appendTimeoutComment(GraphTextWriter writer, int timeout) { - writer.appendNoHilight("/*").newLine(); - writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError")).newLine(); - writer.appendNoHilight(" * ").appendNoHilight(MessageFormat.format(AppResources.translate("decompilationError.timeout"), Helper.formatTimeToText(timeout))).newLine(); - writer.appendNoHilight(" */").newLine(); - writer.appendNoHilight("throw new flash.errors.IllegalOperationError(\""). - appendNoHilight(AppResources.translate("decompilationError.timeout.description")). - appendNoHilight("\");").newLine(); - } - - public static void appendErrorComment(GraphTextWriter writer, Throwable ex) { - writer.appendNoHilight("/*").newLine(); - writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError")).newLine(); - writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError.obfuscated")).newLine(); - if (decompilationErrorAdd != null) { - writer.appendNoHilight(" * ").appendNoHilight(decompilationErrorAdd).newLine(); - } - writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError.errorType")). - appendNoHilight(": " + ex.getClass().getSimpleName() + " (" + ex.getMessage() + ")").newLine(); - writer.appendNoHilight(" */").newLine(); - writer.appendNoHilight("throw new flash.errors.IllegalOperationError(\""). - appendNoHilight(AppResources.translate("decompilationError.error.description")). - appendNoHilight("\");").newLine(); - } - - public static String escapeHTML(String text) { - String[] from = new String[]{"&", "<", ">", "\"", "'", "/"}; - String[] to = new String[]{"&", "<", ">", """, "'", "/"}; - for (int i = 0; i < from.length; i++) { - text = text.replace(from[i], to[i]); - } - return text; - } - - public static String removeInvalidXMLCharacters(String text) { - StringBuilder sb = new StringBuilder(text.length()); - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if (ch > 31 || ch == 9 || ch == 10 || ch == 13) { - sb.append(ch); - } - } - - return sb.toString(); - } - - public static Shape imageToShapeOld(BufferedImage image) { - Area area = new Area(); - Rectangle rectangle = new Rectangle(); - int y1, y2; - int width = image.getWidth(); - int height = image.getHeight(); - - int[] imgData; - int type = image.getType(); - if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) { - imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); - } else { - imgData = image.getRGB(0, 0, width, height, null, 0, width); - } - - BitSet bs = new BitSet(width * height); - bs.set(type); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - int idx = width * y + x; - if ((imgData[idx] >>> 24) > 0) { - bs.set(idx); - } - } - } - - String key = byteArrayToBase64String(bs.toByteArray()); - if (shapeCache.containsKey(key)) { - return shapeCache.get(key); - } - - for (int x = 0; x < width; x++) { - y1 = Integer.MAX_VALUE; - y2 = -1; - for (int y = 0; y < height; y++) { - int rgb = imgData[width * y + x]; - rgb = rgb >>> 24; - if (rgb > 0) { - if (y1 == Integer.MAX_VALUE) { - y1 = y; - y2 = y; - } - if (y > (y2 + 1)) { - rectangle.setBounds(x, y1, 1, y2 - y1 + 1); - area.add(new Area(rectangle)); - y1 = y; - } - y2 = y; - } - } - if ((y2 - y1) >= 0) { - rectangle.setBounds(x, y1, 1, y2 - y1 + 1); - area.add(new Area(rectangle)); - } - } - - shapeCache.put(key, area); - return area; - } - - public static Shape imageToShape(BufferedImage image) { - Area area = new Area(); - int width = image.getWidth(); - int height = image.getHeight(); - - int[] imgData; - int type = image.getType(); - if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) { - imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); - } else { - imgData = image.getRGB(0, 0, width, height, null, 0, width); - } - - BitSet bs = new BitSet(width * height); - bs.set(type); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - int idx = width * y + x; - if ((imgData[idx] >>> 24) > 0) { - bs.set(idx); - } - } - } - - String key = byteArrayToBase64String(bs.toByteArray()); - if (shapeCache.containsKey(key)) { - return shapeCache.get(key); - } - - BitSet bsArea = new BitSet(width * height); - boolean modified = true; - - List leftCoordsX = new ArrayList<>(); - List leftCoordsY = new ArrayList<>(); - List rightCoordsX = new ArrayList<>(); - List rightCoordsY = new ArrayList<>(); - while (modified) { - modified = false; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int idx = width * y + x; - if ((imgData[idx] >>> 24) > 0 && !bsArea.get(idx)) { - leftCoordsX.clear(); - leftCoordsY.clear(); - rightCoordsX.clear(); - rightCoordsY.clear(); - int leftX = x; - int rightX = findRight(imgData, x, y, width); - leftCoordsX.add(leftX); - leftCoordsY.add(y); - rightCoordsX.add(rightX); - rightCoordsY.add(y); - setBitSet(bsArea, leftX, rightX, y, width); - int y2 = y + 1; - while (y2 < height) { - leftCoordsX.add(leftX); - leftCoordsY.add(y2); - rightCoordsX.add(rightX); - rightCoordsY.add(y2); - - int leftX2 = findFirst(imgData, leftX, rightX, y2, width); - if (leftX2 == -1) { - break; - } - - int rightX2 = findRight(imgData, leftX2, y2, width); - - if (leftX2 != leftX) { - leftCoordsX.add(leftX2); - leftCoordsY.add(y2); - } - - if (rightX2 != rightX) { - rightCoordsX.add(rightX2); - rightCoordsY.add(y2); - } - - leftX = leftX2; - rightX = rightX2; - - setBitSet(bsArea, leftX, rightX, y2, width); - y2++; - } - - int cnt = leftCoordsX.size() + rightCoordsX.size(); - int[] xCoords = new int[cnt]; - int[] yCoords = new int[cnt]; - for (int i = 0; i < rightCoordsX.size(); i++) { - xCoords[i] = rightCoordsX.get(i); - yCoords[i] = rightCoordsY.get(i); - } - - int offset = rightCoordsX.size(); - for (int i = 0; i < leftCoordsX.size(); i++) { - int idx2 = leftCoordsX.size() - i - 1; - xCoords[i + offset] = leftCoordsX.get(idx2); - yCoords[i + offset] = leftCoordsY.get(idx2); - } - - Area area2 = new Area(new Polygon(xCoords, yCoords, xCoords.length)); - area.add(area2); - modified = true; - } - } - } - } - - shapeCache.put(key, area); - return area; - } - - private static void setBitSet(BitSet bitSet, int x1, int x2, int y, int width) { - int idx = width * y + x1; - int idx2 = width * y + x2; - for (; idx < idx2; idx++) { - bitSet.set(idx); - } - } - - private static int findFirst(int[] imgData, int x1, int x2, int y, int width) { - int idx = width * y + x1; - if ((imgData[idx] >>> 24) > 0) { - while (x1 > 0 && (imgData[idx - 1] >>> 24) > 0) { - x1--; - idx--; - } - return x1; - } - - int idx2 = width * y + x2; - for (; idx < idx2; idx++) { - if ((imgData[idx] >>> 24) > 0) { - return x1; - } - - x1++; - } - - return -1; - } - - private static int findRight(int[] imgData, int x, int y, int width) { - int result = x; - int idx = width * y + x; - while (result < width && (imgData[idx] >>> 24) > 0) { - result++; - idx++; - } - - return result; - } - - public static void clearShapeCache() { - shapeCache.clear(); - } - - public static String byteArrayToBase64String(byte[] data) { - return DatatypeConverter.printBase64Binary(data); - } - - /** - * Formats double value (removes .0 from end) - * - * @param d - * @return String - */ - public static String doubleStr(double d) { - String ret = Double.toString(d); - if (ret.endsWith(".0")) { - ret = ret.substring(0, ret.length() - 2); - } - return ret; - } - - public static String byteCountStr(long bytes, boolean si) { - int unit = si ? 1000 : 1024; - if (bytes < unit) { - return bytes + " B"; - } - int exp = (int) (Math.log(bytes) / Math.log(unit)); - String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); - return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.helpers; + +import com.jpexs.decompiler.flash.AppResources; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.helpers.Freed; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.awt.Component; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Scanner; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.xml.bind.DatatypeConverter; + +/** + * Class with helper method + * + * @author JPEXS, Paolo Cancedda + */ +public class Helper { + + public static String newLine = System.getProperty("line.separator"); + + public static String hexData = "#hexdata"; + + public static String constants = "#constants"; + + public static String decompilationErrorAdd = null; + + private static final Map shapeCache = new HashMap<>(); + + private static final String[] hexStringCache; + + static { + hexStringCache = new String[256]; + for (int i = 0; i < hexStringCache.length; i++) { + hexStringCache[i] = String.format("%02x", i); + } + } + + /** + * Converts array of int values to string + * + * @param array Array of int values + * @return String representation of the array + */ + public static String intArrToString(int[] array) { + StringBuilder sb = new StringBuilder(); + intArrToStringBuilder(array, sb); + return sb.toString(); + } + + public static void intArrToStringBuilder(int[] array, StringBuilder sb) { + sb.append("["); + for (int i = 0; i < array.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(array[i]); + } + sb.append("]"); + } + + /** + * Converts array of byte values to string + * + * @param array Array of byte values + * @return String representation of the array + */ + public static String byteArrToString(byte[] array) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < array.length; i++) { + if (i > 0) { + sb.append(" "); + } + sb.append(hexStringCache[array[i] & 0xff]); + } + sb.append("]"); + return sb.toString(); + } + + /** + * Adds zeros to beginning of the number to fill specified length. Returns + * as string + * + * @param number Number as string + * @param length Length of new string + * @return Number with added zeros + */ + public static String padZeros(String number, int length) { + int count = length - number.length(); + for (int i = 0; i < count; i++) { + number = "0" + number; + } + return number; + } + + /** + * Formats specified address to four numbers xxxx (or five numbers when + * showing decimal addresses) + * + * @param number Address to format + * @return String representation of the address + */ + public static String formatAddress(long number) { + return formatAddress(number, Configuration.decimalAddress.get()); + } + + /** + * Formats specified address to four numbers xxxx (or five numbers when + * showing decimal addresses) + * + * @param number Address to format + * @param decimal Use decimal format + * @return String representation of the address + */ + public static String formatAddress(long number, boolean decimal) { + if (decimal) { + return String.format("%05d", number); + } + return String.format("%04x", number); + } + + /** + * Escapes string by adding backslashes + * + * @param s String to escape + * @return Escaped string + */ + public static String escapeString(String s) { + StringBuilder ret = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '\n') { + ret.append("\\n"); + } else if (c == '\r') { + ret.append("\\r"); + } else if (c == '\t') { + ret.append("\\t"); + } else if (c == '\b') { + ret.append("\\b"); + } else if (c == '\f') { + ret.append("\\f"); + } else if (c == '\\') { + ret.append("\\\\"); + } else if (c < 32) { + ret.append("\\x").append(byteToHex((byte) c)); + } else { + ret.append(c); + } + } + + return ret.toString(); + } + + /** + * Escapes string by adding backslashes + * + * @param s String to escape + * @return Escaped string + */ + public static String escapeActionScriptString(String s) { + StringBuilder ret = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '\n') { + ret.append("\\n"); + } else if (c == '\r') { + ret.append("\\r"); + } else if (c == '\t') { + ret.append("\\t"); + } else if (c == '\b') { + ret.append("\\b"); + } else if (c == '\f') { + ret.append("\\f"); + } else if (c == '\\') { + ret.append("\\\\"); + } else if (c == '"') { + ret.append("\\\""); + } else if (c == '\'') { + ret.append("\\'"); + } else if (c < 32) { + ret.append("\\x").append(byteToHex((byte) c)); + } else { + ret.append(c); + } + } + + return ret.toString(); + } + + /** + * Escapes string by adding backslashes + * + * @param s String to escape + * @return Escaped string + */ + public static String escapeJavaString(String s) { + StringBuilder ret = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '\n') { + ret.append("\\n"); + } else if (c == '\r') { + ret.append("\\r"); + } else if (c == '\t') { + ret.append("\\t"); + } else if (c == '\b') { + ret.append("\\b"); + } else if (c == '\f') { + ret.append("\\f"); + } else if (c == '\\') { + ret.append("\\\\"); + } else if (c == '"') { + ret.append("\\\""); + } else if (c < 32) { + // \\x is not available in Java string, we should use \\u instead + ret.append("\\u00").append(byteToHex((byte) c)); + } else { + ret.append(c); + } + } + + return ret.toString(); + } + + /** + * Unescapes a string that contains standard Java escape sequences. + *
    + *
  • \b \f \n \r \t \" \' : + * BS, FF, NL, CR, TAB, double and single quote.
  • + *
  • \X \XX \XXX : Octal character + * specification (0 - 377, 0x00 - 0xFF).
  • + *
  • \uXXXX : Hexadecimal based Unicode + * character.
  • + *
+ * + * @param st A string optionally containing standard java escape sequences. + * @return The translated string. + */ + public static String unescapeJavaString(String st) { + + StringBuilder sb = new StringBuilder(st.length()); + + for (int i = 0; i < st.length(); i++) { + char ch = st.charAt(i); + if (ch == '\\') { + char nextChar = (i == st.length() - 1) ? '\\' : st + .charAt(i + 1); + // Octal escape? + if (nextChar >= '0' && nextChar <= '7') { + String code = "" + nextChar; + i++; + if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' + && st.charAt(i + 1) <= '7') { + code += st.charAt(i + 1); + i++; + if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' + && st.charAt(i + 1) <= '7') { + code += st.charAt(i + 1); + i++; + } + } + sb.append((char) Integer.parseInt(code, 8)); + continue; + } + + switch (nextChar) { + case '\\': + ch = '\\'; + break; + case 'b': + ch = '\b'; + break; + case 'f': + ch = '\f'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + case '\"': + ch = '\"'; + break; + case '\'': + ch = '\''; + break; + // Hex Unicode: u???? + case 'u': + if (i >= st.length() - 5) { + ch = 'u'; + break; + } + int code = Integer.parseInt( + "" + st.charAt(i + 2) + st.charAt(i + 3) + + st.charAt(i + 4) + st.charAt(i + 5), 16); + sb.append(Character.toChars(code)); + i += 5; + continue; + } + + i++; + } + + sb.append(ch); + } + + return sb.toString(); + } + + public static String getValidHtmlId(String text) { + // ID and NAME tokens must begin with a letter ([A-Za-z]) and + // may be followed by any number of letters, digits ([0-9]), + // hyphens ("-"), underscores ("_"), colons (":"), and periods ("."). + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if ((ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (i > 0 && ((ch >= '0' && ch <= '9') + || ch == '-' || ch == '_' || ch == ':' || ch == '.'))) { + sb.append(ch); + } else { + sb.append('_'); + } + } + return sb.toString(); + } + + private final static String SPACES12 = " "; + + private final static String ZEROS8 = "00000000"; + + public static String formatHex(int value, int width) { + StringBuilder sb = new StringBuilder(); + sb.append(Integer.toHexString(value)); + if (width > sb.length()) { + sb.insert(0, ZEROS8, 0, width - sb.length()); + } + return sb.toString(); + } + + public static String formatInt(int value, int width) { + StringBuilder sb = new StringBuilder(); + sb.append(value); + if (width > sb.length()) { + sb.insert(0, SPACES12, 0, width - sb.length()); + } + return sb.toString(); + } + + public static String indent(int level, String ss, String indentStr) { + StringBuilder sb = new StringBuilder(); + for (int ii = 0; ii < level; ii++) { + sb.append(indentStr); + } + sb.append(ss); + return sb.toString(); + } + + public static String indentRows(int level, String ss, String indentStr) { + StringBuilder sb = new StringBuilder(); + for (int ii = 0; ii < level; ii++) { + sb.append(indentStr); + } + ss = ss.replaceAll("(\r\n|\r|\n)", "\r\n"); + ss = "\r\n" + ss; + String repl = "\r\n" + sb.toString(); + ss = ss.replace("\r\n", repl); + if (ss.endsWith(repl)) { + ss = ss.substring(0, ss.length() - sb.toString().length()); + } + ss = ss.substring(2); + return ss; + } + + public static String unindentRows(int prefixLineCount, int level, String text) { + StringBuilder sb = new StringBuilder(); + Scanner scanner = new Scanner(text); + String indentStr = ""; + for (int i = 0; i < level; i++) { + indentStr += Configuration.getCodeFormatting().indentString; + } + int indentLength = indentStr.length(); + for (int i = 0; i < prefixLineCount; i++) { + scanner.nextLine(); // ignore line + } + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.startsWith(indentStr)) { + sb.append(line.substring(indentLength)).append(Configuration.getCodeFormatting().newLineChars); + } else { + return sb.toString(); + } + } + return sb.toString(); + } + + public static int getLineCount(String s) { + if (s.endsWith("\r\n")) { + s = s.substring(0, s.length() - 2); + } else if (s.endsWith("\r")) { + s = s.substring(0, s.length() - 1); + } else if (s.endsWith("\n")) { + s = s.substring(0, s.length() - 1); + } + String[] parts = s.split("(\r\n|\r|\n)"); + return parts.length; + } + + public static String padZeros(long number, int length) { + String ret = Long.toString(number); + while (ret.length() < length) { + ret = "0" + ret; + } + return ret; + } + + public static String byteToHex(byte b) { + return hexStringCache[b & 0xff]; + } + + public static String byteArrayToHex(byte[] data) { + StringBuilder sb = new StringBuilder(data.length * 2); + for (byte b : data) { + sb.append(hexStringCache[b & 0xff]); + } + + return sb.toString(); + } + + public static String bytesToHexString(byte[] bytes) { + return bytesToHexString(bytes, 0); + } + + public static String bytesToHexString(byte[] bytes, int start) { + StringBuilder sb = new StringBuilder(); + if (start < bytes.length) { + for (int ii = start; ii < bytes.length; ii++) { + sb.append(formatHex(bytes[ii] & 0xff, 2)); + sb.append(' '); + } + sb.setLength(sb.length() - 1); + } + return sb.toString(); + } + + public static String bytesToHexString(int maxByteCountInString, byte[] bytes, int start) { + if (bytes.length - start <= maxByteCountInString) { + return bytesToHexString(bytes, start); + } + byte[] trailingBytes = new byte[maxByteCountInString / 2]; + byte[] headingBytes = new byte[maxByteCountInString - trailingBytes.length]; + System.arraycopy(bytes, start, headingBytes, 0, headingBytes.length); + int startOfTrailingBytes = bytes.length - trailingBytes.length; + System.arraycopy(bytes, startOfTrailingBytes, trailingBytes, 0, trailingBytes.length); + StringBuilder sb = new StringBuilder(); + sb.append(bytesToHexString(headingBytes, 0)); + if (trailingBytes.length > 0) { + sb.append(" ... "); + sb.append(bytesToHexString(trailingBytes, 0)); + } + return sb.toString(); + } + + public static String format(String str, int len) { + if (len <= str.length()) { + return str; + } + StringBuilder sb = new StringBuilder(str); + for (int ii = str.length(); ii < len; ii++) { + sb.append(' '); + } + return sb.toString(); + } + + public static String joinStrings(Iterable arr, String glue) { + StringBuilder ret = new StringBuilder(); + boolean first = true; + for (Object s : arr) { + if (!first) { + ret.append(glue); + } else { + first = false; + } + ret.append(s); + } + return ret.toString(); + } + + public static String joinStrings(String[] arr, String glue) { + StringBuilder ret = new StringBuilder(); + boolean first = true; + for (String s : arr) { + if (!first) { + ret.append(glue); + } else { + first = false; + } + ret.append(s); + } + return ret.toString(); + } + + public static String joinStrings(List arr, String formatString, String glue) { + StringBuilder ret = new StringBuilder(); + boolean first = true; + for (String s : arr) { + if (!first) { + ret.append(glue); + } else { + first = false; + } + ret.append(String.format(formatString, s)); + } + return ret.toString(); + } + + public static String joinStrings(String[] arr, String formatString, String glue) { + StringBuilder ret = new StringBuilder(); + boolean first = true; + for (String s : arr) { + if (!first) { + ret.append(glue); + } else { + first = false; + } + ret.append(String.format(formatString, s)); + } + return ret.toString(); + } + + @SuppressWarnings("unchecked") + public static E deepCopy(E o) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(o); + oos.flush(); + } + E copy; + try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + copy = (E) ois.readObject(); + } + return copy; + } catch (IOException | ClassNotFoundException ex) { + Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, "Copy error", ex); + return null; + } + } + + public static List toList(Object... rest) { + List ret = new ArrayList<>(); + ret.addAll(Arrays.asList(rest)); + return ret; + } + + public static ByteArrayInputStream getInputStream(byte[]... data) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + try { + for (byte[] d : data) { + baos.write(d); + } + } catch (IOException iex) { + } + return new ByteArrayInputStream(baos.toByteArray()); + } + + public static byte[] readFile(String... file) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (String f : file) { + try (FileInputStream fis = new FileInputStream(f)) { + byte[] buf = new byte[4096]; + int cnt = 0; + while ((cnt = fis.read(buf)) > 0) { + baos.write(buf, 0, cnt); + } + } catch (IOException ex) { + Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); + } + } + return baos.toByteArray(); + } + + public static String readTextFile(String... file) { + byte[] data = readFile(file); + if (data.length > 1 && data[0] == (byte) 0xef && data[1] == (byte) 0xbb && data[2] == (byte) 0xbf) { + // remove UTF-8 BOM + return new String(data, 3, data.length - 3, Utf8Helper.charset); + } + + return new String(data, Utf8Helper.charset); + } + + public static byte[] readStream(InputStream is) { + if (is instanceof MemoryInputStream) { + return ((MemoryInputStream) is).getAllRead(); + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copyStream(is, baos, Long.MAX_VALUE); + return baos.toByteArray(); + } + + public static void copyStream(InputStream is, OutputStream os, long maxLength) { + try { + final int bufSize = 4096; + byte[] buf = new byte[bufSize]; + int cnt = 0; + while ((cnt = is.read(buf)) > 0) { + os.write(buf, 0, cnt); + maxLength -= cnt; + + // last chunk is smaller + if (maxLength < bufSize) { + buf = new byte[(int) maxLength]; + } + } + } catch (IOException ex) { + // ignore + } + } + + public static void writeFile(String file, byte[]... data) { + try (FileOutputStream fos = new FileOutputStream(file)) { + for (byte[] d : data) { + fos.write(d); + } + } catch (IOException ex) { + // ignore + } + } + + public static String stackToString(TranslateStack stack, LocalData localData) throws InterruptedException { + String ret = "["; + for (int i = stack.size() - 1; i >= 0; i--) { + if (i < stack.size() - 1) { + ret += ", "; + } + ret += stack.get(i).toString(localData); + } + ret += "]"; + return ret; + } + + public static File fixDialogFile(File f) { + Pattern pat = Pattern.compile("\"([^\"]+)\""); + String name = f.getAbsolutePath(); + Matcher m = pat.matcher(name); + if (m.find()) { + f = new File(m.group(1)); + } + return f; + } + + private static final BitSet fileNameInvalidChars; + + private static final List invalidFilenamesParts; + + static { + BitSet toEncode = new BitSet(256); + + for (int i = 0; i < 32; i++) { + toEncode.set(i); + } + + toEncode.set('\\'); + toEncode.set('/'); + toEncode.set(':'); + toEncode.set('*'); + toEncode.set('?'); + toEncode.set('"'); + toEncode.set('<'); + toEncode.set('>'); + toEncode.set('|'); + + fileNameInvalidChars = toEncode; + + //windows reserved filenames: + invalidFilenamesParts = new ArrayList<>(); + invalidFilenamesParts.add("CON"); + invalidFilenamesParts.add("PRN"); + invalidFilenamesParts.add("AUX"); + invalidFilenamesParts.add("CLOCK$"); + invalidFilenamesParts.add("NUL"); + for (int i = 1; i <= 9; i++) { + invalidFilenamesParts.add("COM" + i); + invalidFilenamesParts.add("LPT" + i); + } + } + + public static String makeFileName(String str) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + int ch = (int) str.charAt(i); + if (ch < 256 && fileNameInvalidChars.get(ch)) { + sb.append("%").append(String.format("%02X", ch)); + } else { + sb.append((char) ch); + } + } + str = sb.toString(); + if (str.endsWith(" ")) { + str = str.substring(0, str.length() - 1) + "%20"; + } + if (str.endsWith(".")) { + str = str.substring(0, str.length() - 1) + "%2E"; + } + str = "." + str + "."; + for (String inv : invalidFilenamesParts) { + str = Pattern.compile("\\." + Pattern.quote(inv) + "\\.", Pattern.CASE_INSENSITIVE).matcher(str).replaceAll("._" + inv + "."); + } + str = str.substring(1, str.length() - 1); //remove dots + if (str.isEmpty()) { + str = "unnamed"; + } + return str; + } + + public static String strToHex(String s) { + byte[] bs = Utf8Helper.getBytes(s); + String sn = ""; + for (int i = 0; i < bs.length; i++) { + sn += "0x" + Integer.toHexString(bs[i] & 0xff) + " "; + } + return sn; + } + + public static void emptyObject(Object obj) { + Field[] fields = obj.getClass().getDeclaredFields(); + for (Field f : fields) { + if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC + || f.getType().isPrimitive()) { + continue; + } + try { + f.setAccessible(true); + + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); + + Object v = f.get(obj); + if (v != null) { + try { + if (v instanceof Collection) { + ((Collection) v).clear(); + } + if (v instanceof Component) { + if (((Component) v).getParent() != null) { + ((Component) v).getParent().remove((Component) v); + } + } + if (v instanceof Freed) { + Freed freed = ((Freed) v); + if (!freed.isFreeing()) { + ((Freed) v).free(); + } + } + } catch (Throwable t) { + } + + f.set(obj, null); + } + } catch (UnsupportedOperationException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException ex) { + throw new Error(ex); + } + } + } + + public static String formatTimeSec(long timeMs) { + long timeS = timeMs / 1000; + timeMs %= 1000; + long timeM = timeS / 60; + timeS %= 60; + long timeH = timeM / 60; + timeM %= 60; + String timeStr = ""; + if (timeH > 0) { + timeStr += Helper.padZeros(timeH, 2) + ":"; + } + timeStr += Helper.padZeros(timeM, 2) + ":"; + timeStr += Helper.padZeros(timeS, 2) + "." + Helper.padZeros(timeMs, 3); + return timeStr; + } + + public static String formatFileSize(long fileSizeLong) { + double fileSize = fileSizeLong; + if (fileSize < 1024) { + return String.format("%d bytes", fileSizeLong); + } + fileSize /= 1024; + if (fileSize < 1024) { + return String.format("%.2f KB", fileSize); + } + fileSize /= 1024; + return String.format("%.2f MB", fileSize); + } + + public static void freeMem() { + Cache.clearAll(); + System.gc(); + } + + public static String formatTimeToText(int timeS) { + long timeM = timeS / 60; + timeS %= 60; + long timeH = timeM / 60; + timeM %= 60; + + String timeStr = ""; + String strAnd = AppResources.translate("timeFormat.and"); + String strHour = AppResources.translate("timeFormat.hour"); + String strHours = AppResources.translate("timeFormat.hours"); + String strMinute = AppResources.translate("timeFormat.minute"); + String strMinutes = AppResources.translate("timeFormat.minutes"); + String strSecond = AppResources.translate("timeFormat.second"); + String strSeconds = AppResources.translate("timeFormat.seconds"); + + if (timeH > 0) { + timeStr += timeH + " " + (timeH > 1 ? strHours : strHour); + } + if (timeM > 0) { + if (timeStr.length() > 0) { + timeStr += " " + strAnd + " "; + } + timeStr += timeM + " " + (timeM > 1 ? strMinutes : strMinute); + } + if (timeS > 0) { + if (timeStr.length() > 0) { + timeStr += " " + strAnd + " "; + } + timeStr += timeS + " " + (timeS > 1 ? strSeconds : strSecond); + } + + // (currently) used only in log, so no localization is required + return timeStr; + } + + public static GraphTextWriter byteArrayToHexWithHeader(GraphTextWriter writer, byte[] data) { + writer.appendNoHilight("#hexdata").newLine().newLine(); + return byteArrayToHex(writer, data, 8, 8, false, false); + } + + public static GraphTextWriter byteArrayToHex(GraphTextWriter writer, byte[] data, int bytesPerRow, int groupSize, boolean addChars, boolean showAddress) { + + /* // hex data from decompiled actions + Scanner scanner = new Scanner(srcWithHex); + while (scanner.hasNextLine()) { + String line = scanner.nextLine().trim(); + if (line.startsWith(";")) { + result.append(line.substring(1).trim()).append(nl); + } else { + result.append(";").append(line).append(nl); + } + }*/ + int length = data.length; + + int rowCount = length / bytesPerRow; + if (length % bytesPerRow > 0) { + rowCount++; + } + + long address = 0; + for (int row = 0; row < rowCount; row++) { + if (row > 0) { + writer.newLine(); + } + + if (showAddress) { + writer.appendNoHilight("0x" + String.format("%08x ", address)); + } + + for (int i = 0; i < bytesPerRow; i++) { + int idx = row * bytesPerRow + i; + if (length > idx) { + if (i > 0 && i % groupSize == 0) { + writer.appendNoHilight(" "); + } + writer.appendNoHilight(byteToHex(data[idx])).appendNoHilight(" "); + } else { + if (addChars) { + if (i > 0 && i % groupSize == 0) { + writer.appendNoHilight(" "); + } + writer.appendNoHilight(" "); + } + } + address += bytesPerRow; + } + + if (addChars) { + writer.appendNoHilight(" "); + for (int i = 0; i < bytesPerRow; i++) { + int idx = row * bytesPerRow + i; + if (length == idx) { + break; + } + if (i > 0 && i % groupSize == 0) { + writer.appendNoHilight(" "); + } + byte ch = data[idx]; + if (ch >= 0 && ch < 32) { + ch = '.'; + } + writer.appendNoHilight((char) ch + ""); + } + } + } + + writer.newLine(); + return writer; + } + + public static byte[] getBytesFromHexaText(String text) { + Scanner scanner = new Scanner(text); + scanner.nextLine(); // ignore first line + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + while (scanner.hasNextLine()) { + String line = scanner.nextLine().trim(); + if (line.startsWith(";")) { + continue; + } + line = line.replace(" ", ""); + for (int i = 0; i < line.length() / 2; i++) { + String hexStr = line.substring(i * 2, (i + 1) * 2); + byte b = (byte) Integer.parseInt(hexStr, 16); + baos.write(b); + } + } + byte[] data = baos.toByteArray(); + return data; + } + + public static List> getConstantPoolsFromText(String text) { + Scanner scanner = new Scanner(text); + scanner.nextLine(); // ignore first line + List> result = new ArrayList<>(); + List cPool = new ArrayList<>(); + result.add(cPool); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.startsWith("---")) { + cPool = new ArrayList<>(); + result.add(cPool); + } + + String[] parts = line.split("\\|", 2); + if (parts.length >= 2) { + cPool.add(unescapeJavaString(parts[1])); + } + } + + return result; + } + + public static boolean contains(int[] array, int value) { + if (array == null) { + return false; + } + + for (int i : array) { + if (i == value) { + return true; + } + } + return false; + } + + public static void saveStream(InputStream is, File output) throws IOException { + byte[] buf = new byte[4096]; + int cnt; + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(output))) { + while ((cnt = is.read(buf)) > 0) { + fos.write(buf, 0, cnt); + fos.flush(); + } + } + } + + public static String getDecompilationSkippedComment() { + return "// " + AppResources.translate("decompilation.skipped"); + } + + public static void appendTimeoutComment(GraphTextWriter writer, int timeout) { + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError")).newLine(); + writer.appendNoHilight(" * ").appendNoHilight(MessageFormat.format(AppResources.translate("decompilationError.timeout"), Helper.formatTimeToText(timeout))).newLine(); + writer.appendNoHilight(" */").newLine(); + writer.appendNoHilight("throw new flash.errors.IllegalOperationError(\""). + appendNoHilight(AppResources.translate("decompilationError.timeout.description")). + appendNoHilight("\");").newLine(); + } + + public static void appendErrorComment(GraphTextWriter writer, Throwable ex) { + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError")).newLine(); + writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError.obfuscated")).newLine(); + if (decompilationErrorAdd != null) { + writer.appendNoHilight(" * ").appendNoHilight(decompilationErrorAdd).newLine(); + } + writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError.errorType")). + appendNoHilight(": " + ex.getClass().getSimpleName() + " (" + ex.getMessage() + ")").newLine(); + writer.appendNoHilight(" */").newLine(); + writer.appendNoHilight("throw new flash.errors.IllegalOperationError(\""). + appendNoHilight(AppResources.translate("decompilationError.error.description")). + appendNoHilight("\");").newLine(); + } + + public static String escapeHTML(String text) { + String[] from = new String[]{"&", "<", ">", "\"", "'", "/"}; + String[] to = new String[]{"&", "<", ">", """, "'", "/"}; + for (int i = 0; i < from.length; i++) { + text = text.replace(from[i], to[i]); + } + return text; + } + + public static String removeInvalidXMLCharacters(String text) { + StringBuilder sb = new StringBuilder(text.length()); + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (ch > 31 || ch == 9 || ch == 10 || ch == 13) { + sb.append(ch); + } + } + + return sb.toString(); + } + + public static Shape imageToShapeOld(BufferedImage image) { + Area area = new Area(); + Rectangle rectangle = new Rectangle(); + int y1, y2; + int width = image.getWidth(); + int height = image.getHeight(); + + int[] imgData; + int type = image.getType(); + if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) { + imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + } else { + imgData = image.getRGB(0, 0, width, height, null, 0, width); + } + + BitSet bs = new BitSet(width * height); + bs.set(type); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + int idx = width * y + x; + if ((imgData[idx] >>> 24) > 0) { + bs.set(idx); + } + } + } + + String key = byteArrayToBase64String(bs.toByteArray()); + if (shapeCache.containsKey(key)) { + return shapeCache.get(key); + } + + for (int x = 0; x < width; x++) { + y1 = Integer.MAX_VALUE; + y2 = -1; + for (int y = 0; y < height; y++) { + int rgb = imgData[width * y + x]; + rgb = rgb >>> 24; + if (rgb > 0) { + if (y1 == Integer.MAX_VALUE) { + y1 = y; + y2 = y; + } + if (y > (y2 + 1)) { + rectangle.setBounds(x, y1, 1, y2 - y1 + 1); + area.add(new Area(rectangle)); + y1 = y; + } + y2 = y; + } + } + if ((y2 - y1) >= 0) { + rectangle.setBounds(x, y1, 1, y2 - y1 + 1); + area.add(new Area(rectangle)); + } + } + + shapeCache.put(key, area); + return area; + } + + public static Shape imageToShape(BufferedImage image) { + Area area = new Area(); + int width = image.getWidth(); + int height = image.getHeight(); + + int[] imgData; + int type = image.getType(); + if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) { + imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + } else { + imgData = image.getRGB(0, 0, width, height, null, 0, width); + } + + BitSet bs = new BitSet(width * height); + bs.set(type); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + int idx = width * y + x; + if ((imgData[idx] >>> 24) > 0) { + bs.set(idx); + } + } + } + + String key = byteArrayToBase64String(bs.toByteArray()); + if (shapeCache.containsKey(key)) { + return shapeCache.get(key); + } + + BitSet bsArea = new BitSet(width * height); + boolean modified = true; + + List leftCoordsX = new ArrayList<>(); + List leftCoordsY = new ArrayList<>(); + List rightCoordsX = new ArrayList<>(); + List rightCoordsY = new ArrayList<>(); + while (modified) { + modified = false; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int idx = width * y + x; + if ((imgData[idx] >>> 24) > 0 && !bsArea.get(idx)) { + leftCoordsX.clear(); + leftCoordsY.clear(); + rightCoordsX.clear(); + rightCoordsY.clear(); + int leftX = x; + int rightX = findRight(imgData, x, y, width); + leftCoordsX.add(leftX); + leftCoordsY.add(y); + rightCoordsX.add(rightX); + rightCoordsY.add(y); + setBitSet(bsArea, leftX, rightX, y, width); + int y2 = y + 1; + while (y2 < height) { + leftCoordsX.add(leftX); + leftCoordsY.add(y2); + rightCoordsX.add(rightX); + rightCoordsY.add(y2); + + int leftX2 = findFirst(imgData, leftX, rightX, y2, width); + if (leftX2 == -1) { + break; + } + + int rightX2 = findRight(imgData, leftX2, y2, width); + + if (leftX2 != leftX) { + leftCoordsX.add(leftX2); + leftCoordsY.add(y2); + } + + if (rightX2 != rightX) { + rightCoordsX.add(rightX2); + rightCoordsY.add(y2); + } + + leftX = leftX2; + rightX = rightX2; + + setBitSet(bsArea, leftX, rightX, y2, width); + y2++; + } + + int cnt = leftCoordsX.size() + rightCoordsX.size(); + int[] xCoords = new int[cnt]; + int[] yCoords = new int[cnt]; + for (int i = 0; i < rightCoordsX.size(); i++) { + xCoords[i] = rightCoordsX.get(i); + yCoords[i] = rightCoordsY.get(i); + } + + int offset = rightCoordsX.size(); + for (int i = 0; i < leftCoordsX.size(); i++) { + int idx2 = leftCoordsX.size() - i - 1; + xCoords[i + offset] = leftCoordsX.get(idx2); + yCoords[i + offset] = leftCoordsY.get(idx2); + } + + Area area2 = new Area(new Polygon(xCoords, yCoords, xCoords.length)); + area.add(area2); + modified = true; + } + } + } + } + + shapeCache.put(key, area); + return area; + } + + private static void setBitSet(BitSet bitSet, int x1, int x2, int y, int width) { + int idx = width * y + x1; + int idx2 = width * y + x2; + for (; idx < idx2; idx++) { + bitSet.set(idx); + } + } + + private static int findFirst(int[] imgData, int x1, int x2, int y, int width) { + int idx = width * y + x1; + if ((imgData[idx] >>> 24) > 0) { + while (x1 > 0 && (imgData[idx - 1] >>> 24) > 0) { + x1--; + idx--; + } + return x1; + } + + int idx2 = width * y + x2; + for (; idx < idx2; idx++) { + if ((imgData[idx] >>> 24) > 0) { + return x1; + } + + x1++; + } + + return -1; + } + + private static int findRight(int[] imgData, int x, int y, int width) { + int result = x; + int idx = width * y + x; + while (result < width && (imgData[idx] >>> 24) > 0) { + result++; + idx++; + } + + return result; + } + + public static void clearShapeCache() { + shapeCache.clear(); + } + + public static String byteArrayToBase64String(byte[] data) { + return DatatypeConverter.printBase64Binary(data); + } + + /** + * Formats double value (removes .0 from end) + * + * @param d + * @return String + */ + public static String doubleStr(double d) { + String ret = Double.toString(d); + if (ret.endsWith(".0")) { + ret = ret.substring(0, ret.length() - 2); + } + return ret; + } + + public static String byteCountStr(long bytes, boolean si) { + int unit = si ? 1000 : 1024; + if (bytes < unit) { + return bytes + " B"; + } + int exp = (int) (Math.log(bytes) / Math.log(unit)); + String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); + return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); + } + + public static List safePackageSplit(String name) { + List parts = new ArrayList<>(); + if (name.contains(".")) { + String[] partsArr = name.split("\\."); + parts.addAll(Arrays.asList(partsArr)); + //Fix for name starting with "." - Obfuscated handling + if (parts.get(0).equals("")) { + parts.remove(0); + parts.set(0, "." + parts.get(0)); + } + } else { + parts.add(name); + } + return parts; + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 0c480958a..b8029c337 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -1,1502 +1,1499 @@ -/* - * Copyright (C) 2010-2015 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui; - -import com.jpexs.decompiler.flash.ApplicationInfo; -import com.jpexs.decompiler.flash.EventListener; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; -import com.jpexs.decompiler.flash.SWFSourceInfo; -import com.jpexs.decompiler.flash.SearchMode; -import com.jpexs.decompiler.flash.SwfOpenException; -import com.jpexs.decompiler.flash.Version; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; -import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; -import com.jpexs.decompiler.flash.console.ContextMenuTools; -import com.jpexs.decompiler.flash.gui.pipes.FirstInstance; -import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.treeitems.SWFList; -import com.jpexs.helpers.Cache; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.Path; -import com.jpexs.helpers.ProgressListener; -import com.jpexs.helpers.Stopwatch; -import com.jpexs.helpers.streams.SeekableInputStream; -import com.sun.jna.Platform; -import com.sun.jna.platform.win32.Advapi32Util; -import com.sun.jna.platform.win32.Kernel32; -import com.sun.jna.platform.win32.WinReg; -import java.awt.AWTException; -import java.awt.Frame; -import java.awt.GraphicsEnvironment; -import java.awt.MenuItem; -import java.awt.PopupMenu; -import java.awt.SystemTray; -import java.awt.TrayIcon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.URL; -import java.net.URLConnection; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.Map.Entry; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.logging.ConsoleHandler; -import java.util.logging.FileHandler; -import java.util.logging.Formatter; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.SwingWorker; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.filechooser.FileFilter; -import org.pushingpixels.substance.api.SubstanceLookAndFeel; - -/** - * Main executable class - * - * @author JPEXS - */ -public class Main { - - protected static ProxyFrame proxyFrame; - - private static List sourceInfos = new ArrayList<>(); - - public static LoadingDialog loadingDialog; - - private static boolean working = false; - - private static TrayIcon trayIcon; - - private static MenuItem stopMenuItem; - - private static MainFrame mainFrame; - - public static final int UPDATE_SYSTEM_MAJOR = 1; - - public static final int UPDATE_SYSTEM_MINOR = 3; - - private static LoadFromMemoryFrame loadFromMemoryFrame; - - private static LoadFromCacheFrame loadFromCacheFrame; - - private static final Logger logger = Logger.getLogger(Main.class.getName()); - - public static DebugLogDialog debugDialog; - - public static boolean shouldCloseWhenClosingLoadingDialog; - - public static void ensureMainFrame() { - if (mainFrame == null) { - synchronized (Main.class) { - if (mainFrame == null) { - MainFrame frame; - if (Configuration.useRibbonInterface.get()) { - frame = new MainFrameRibbon(); - } else { - frame = new MainFrameClassic(); - } - frame.getPanel().setErrorState(ErrorLogFrame.getInstance().getErrorState()); - mainFrame = frame; - } - } - } - } - - public static MainFrame getMainFrame() { - return mainFrame; - } - - public static void loadFromCache() { - if (loadFromCacheFrame == null) { - loadFromCacheFrame = new LoadFromCacheFrame(); - } - loadFromCacheFrame.setVisible(true); - } - - public static void loadFromMemory() { - if (loadFromMemoryFrame == null) { - loadFromMemoryFrame = new LoadFromMemoryFrame(mainFrame); - } - loadFromMemoryFrame.setVisible(true); - } - - public static void setSubLimiter(boolean value) { - if (value) { - AVM2Code.toSourceLimit = Configuration.sublimiter.get(); - } else { - AVM2Code.toSourceLimit = -1; - } - } - - public static boolean isWorking() { - return working; - } - - public static void startProxy(int port) { - if (proxyFrame == null) { - proxyFrame = new ProxyFrame(mainFrame); - } - - proxyFrame.setPort(port); - addTrayIcon(); - switchProxy(); - } - - public static void showProxy() { - if (proxyFrame == null) { - proxyFrame = new ProxyFrame(mainFrame); - } - proxyFrame.setVisible(true); - proxyFrame.setState(Frame.NORMAL); - } - - public static void startWork(String name) { - startWork(name, -1, null); - } - - public static void startWork(String name, int percent) { - startWork(name, percent, null); - } - - public static void startWork(String name, CancellableWorker worker) { - startWork(name, -1, worker); - } - - public static void startWork(final String name, final int percent, final CancellableWorker worker) { - working = true; - View.execInEventDispatchLater(() -> { - if (mainFrame != null) { - mainFrame.getPanel().setWorkStatus(name, worker); - if (percent == -1) { - mainFrame.getPanel().hidePercent(); - } else { - mainFrame.getPanel().setPercent(percent); - } - } - if (loadingDialog != null) { - loadingDialog.setDetail(name); - loadingDialog.setPercent(percent); - } - if (CommandLineArgumentParser.isCommandLineMode()) { - System.out.println(name); - } - }); - } - - public static void stopWork() { - working = false; - View.execInEventDispatchLater(() -> { - if (mainFrame != null) { - mainFrame.getPanel().setWorkStatus("", null); - } - if (loadingDialog != null) { - loadingDialog.setDetail(""); - } - }); - } - - public static SWFList parseSWF(SWFSourceInfo sourceInfo) throws Exception { - SWFList result = new SWFList(); - - InputStream inputStream = sourceInfo.getInputStream(); - SWFBundle bundle = null; - FileInputStream fis = null; - if (inputStream == null) { - inputStream = new BufferedInputStream(fis = new FileInputStream(sourceInfo.getFile())); - bundle = sourceInfo.getBundle(false, SearchMode.ALL); - logger.log(Level.INFO, "Load file: {0}", sourceInfo.getFile()); - } else if (inputStream instanceof SeekableInputStream - || inputStream instanceof BufferedInputStream) { - try { - inputStream.reset(); - } catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); - } - logger.log(Level.INFO, "Load stream: {0}", sourceInfo.getFileTitle()); - } - - Stopwatch sw = Stopwatch.startNew(); - if (bundle != null) { - result.bundle = bundle; - result.name = new File(sourceInfo.getFileTitleOrName()).getName(); - for (Entry streamEntry : bundle.getAll().entrySet()) { - InputStream stream = streamEntry.getValue(); - stream.reset(); - CancellableWorker worker = new CancellableWorker() { - @Override - public SWF doInBackground() throws Exception { - SWF swf = new SWF(stream, null, streamEntry.getKey(), new ProgressListener() { - @Override - public void progress(int p) { - startWork(AppStrings.translate("work.reading.swf"), p); - } - }, Configuration.parallelSpeedUp.get()); - return swf; - } - }; - loadingDialog.setWroker(worker); - worker.execute(); - - try { - result.add(worker.get()); - } catch (CancellationException ex) { - logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", streamEntry.getKey()); - } - } - } else { - InputStream fInputStream = inputStream; - CancellableWorker worker = new CancellableWorker() { - @Override - public SWF doInBackground() throws Exception { - SWF swf = new SWF(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle(), new ProgressListener() { - @Override - public void progress(int p) { - startWork(AppStrings.translate("work.reading.swf"), p); - } - }, Configuration.parallelSpeedUp.get()); - return swf; - } - }; - if (loadingDialog != null) { - loadingDialog.setWroker(worker); - } - worker.execute(); - - try { - result.add(worker.get()); - } catch (CancellationException ex) { - logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", sourceInfo.getFileTitleOrName()); - } - } - - if (fis != null) { - logger.log(Level.INFO, "File loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000)); - fis.close(); - } else { - logger.log(Level.INFO, "Stream loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000)); - } - - result.sourceInfo = sourceInfo; - for (SWF swf : result) { - logger.log(Level.INFO, ""); - logger.log(Level.INFO, "== File information =="); - logger.log(Level.INFO, "Size: {0}", Helper.formatFileSize(swf.fileSize)); - logger.log(Level.INFO, "Flash version: {0}", swf.version); - int width = (int) ((swf.displayRect.Xmax - swf.displayRect.Xmin) / SWF.unitDivisor); - int height = (int) ((swf.displayRect.Ymax - swf.displayRect.Ymin) / SWF.unitDivisor); - logger.log(Level.INFO, "Width: {0}", width); - logger.log(Level.INFO, "Height: {0}", height); - - swf.swfList = result; - swf.addEventListener(new EventListener() { - @Override - public void handleExportingEvent(String type, int index, int count, Object data) { - String text = AppStrings.translate("work.exporting"); - if (type != null && type.length() > 0) { - text += " " + type; - } - - startWork(text + " " + index + "/" + count + " " + data); - } - - @Override - public void handleExportedEvent(String type, int index, int count, Object data) { - String text = AppStrings.translate("work.exported"); - if (type != null && type.length() > 0) { - text += " " + type; - } - - startWork(text + " " + index + "/" + count + " " + data); - } - - @Override - public void handleEvent(String event, Object data) { - if (event.equals("exporting") || event.equals("exported")) { - throw new Error("Event is not supported by this handler."); - } - if (event.equals("getVariables")) { - startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); - } - if (event.equals("deobfuscate")) { - startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); - } - if (event.equals("rename")) { - startWork(AppStrings.translate("work.renaming") + "..." + (String) data); - } - } - }); - } - - return result; - } - - public static void saveFile(SWF swf, String outfile) throws IOException { - saveFile(swf, outfile, SaveFileMode.SAVE); - } - - public static void saveFile(SWF swf, String outfile, SaveFileMode mode) throws IOException { - if (mode == SaveFileMode.SAVEAS && !swf.swfList.isBundle()) { - swf.setFile(outfile); - swf.swfList.sourceInfo.setFile(outfile); - } - File outfileF = new File(outfile); - File tmpFile = new File(outfile + ".tmp"); - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(tmpFile))) { - if (mode == SaveFileMode.EXE) { - InputStream exeStream = View.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/Swf2Exe.bin"); - byte[] buffer = new byte[4096]; - int bytesRead; - while ((bytesRead = exeStream.read(buffer)) != -1) { - fos.write(buffer, 0, bytesRead); - } - int width = swf.displayRect.Xmax - swf.displayRect.Xmin; - int height = swf.displayRect.Ymax - swf.displayRect.Ymin; - fos.write(width & 0xff); - fos.write((width >> 8) & 0xff); - fos.write((width >> 16) & 0xff); - fos.write((width >> 24) & 0xff); - fos.write(height & 0xff); - fos.write((height >> 8) & 0xff); - fos.write((height >> 16) & 0xff); - fos.write((height >> 24) & 0xff); - fos.write(Configuration.saveAsExeScaleMode.get()); - } - swf.saveTo(fos); - } - if (tmpFile.exists()) { - if (tmpFile.length() > 0) { - outfileF.delete(); - if (!tmpFile.renameTo(outfileF)) { - tmpFile.delete(); - throw new IOException("Cannot access " + outfile); - } - } else { - throw new IOException("Output is empty"); - } - } - } - - private static class OpenFileWorker extends SwingWorker { - - private final SWFSourceInfo[] sourceInfos; - - private final Runnable executeAfterOpen; - - public OpenFileWorker(SWFSourceInfo sourceInfo) { - this(sourceInfo, null); - } - - public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { - this.sourceInfos = new SWFSourceInfo[]{sourceInfo}; - this.executeAfterOpen = executeAfterOpen; - } - - public OpenFileWorker(SWFSourceInfo[] sourceInfos) { - this(sourceInfos, null); - } - - public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen) { - this.sourceInfos = sourceInfos; - this.executeAfterOpen = executeAfterOpen; - } - - @Override - protected Object doInBackground() throws Exception { - boolean first = true; - SWF firstSWF = null; - for (final SWFSourceInfo sourceInfo : sourceInfos) { - SWFList swfs = null; - try { - Main.startWork(AppStrings.translate("work.reading.swf") + "..."); - try { - swfs = parseSWF(sourceInfo); - } catch (ExecutionException ex) { - Throwable cause = ex.getCause(); - if (cause instanceof SwfOpenException) { - throw (SwfOpenException) cause; - } - - throw ex; - } - } catch (OutOfMemoryError ex) { - logger.log(Level.SEVERE, null, ex); - View.showMessageDialog(null, "Cannot load SWF file. Out of memory."); - continue; - } catch (SwfOpenException ex) { - logger.log(Level.SEVERE, null, ex); - View.showMessageDialog(null, ex.getMessage()); - continue; - } catch (Exception ex) { - logger.log(Level.SEVERE, null, ex); - View.showMessageDialog(null, "Cannot load SWF file."); - continue; - } - - final SWFList swfs1 = swfs; - final boolean first1 = first; - first = false; - if (firstSWF == null) { - firstSWF = swfs1.get(0); - } - - try { - View.execInEventDispatch(() -> { - Main.startWork(AppStrings.translate("work.creatingwindow") + "..."); - ensureMainFrame(); - mainFrame.getPanel().load(swfs1, first1); - }); - } catch (Exception ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - loadingDialog.setVisible(false); - shouldCloseWhenClosingLoadingDialog = false; - - final SWF fswf = firstSWF; - View.execInEventDispatch(() -> { - if (mainFrame != null) { - mainFrame.setVisible(true); - } - - Main.stopWork(); - - if (mainFrame != null && Configuration.gotoMainClassOnStartup.get()) { - mainFrame.getPanel().gotoDocumentClass(fswf); - } - - if (mainFrame != null && fswf != null) { - SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(fswf.getShortFileName()); - if (swfConf != null) { - String pathStr = swfConf.lastSelectedPath; - mainFrame.getPanel().tagTree.setSelectionPathString(pathStr); - } - } - - if (executeAfterOpen != null) { - executeAfterOpen.run(); - } - }); - - return true; - } - } - - public static boolean reloadSWFs() { - CancellableWorker.cancelBackgroundThreads(); - if (Main.sourceInfos.isEmpty()) { - Helper.freeMem(); - showModeFrame(); - return true; - } else { - SWFSourceInfo[] sourceInfosCopy = new SWFSourceInfo[sourceInfos.size()]; - sourceInfos.toArray(sourceInfosCopy); - sourceInfos.clear(); - openFile(sourceInfosCopy); - return true; - } - } - - public static void reloadApp() { - if (debugDialog != null) { - debugDialog.setVisible(false); - debugDialog.dispose(); - debugDialog = null; - } - if (loadingDialog != null) { - synchronized (Main.class) { - if (loadingDialog != null) { - loadingDialog.setVisible(false); - loadingDialog.dispose(); - loadingDialog = null; - } - } - } - if (proxyFrame != null) { - proxyFrame.setVisible(false); - proxyFrame.dispose(); - proxyFrame = null; - } - if (loadFromMemoryFrame != null) { - loadFromMemoryFrame.setVisible(false); - loadFromMemoryFrame.dispose(); - loadFromMemoryFrame = null; - } - if (loadFromCacheFrame != null) { - loadFromCacheFrame.setVisible(false); - loadFromCacheFrame.dispose(); - loadFromCacheFrame = null; - } - if (mainFrame != null) { - mainFrame.setVisible(false); - mainFrame.getPanel().closeAll(); - mainFrame.dispose(); - mainFrame = null; - } - FontTag.reload(); - Cache.clearAll(); - initGui(); - reloadSWFs(); - } - - public static OpenFileResult openFile(String swfFile, String fileTitle) { - return openFile(swfFile, fileTitle, null); - } - - public static OpenFileResult openFile(String swfFile, String fileTitle, Runnable executeAfterOpen) { - try { - File file = new File(swfFile); - if (!file.exists()) { - View.showMessageDialog(null, AppStrings.translate("open.error.fileNotFound"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); - return OpenFileResult.NOT_FOUND; - } - swfFile = file.getCanonicalPath(); - Configuration.addRecentFile(swfFile); - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, swfFile, fileTitle); - OpenFileResult openResult = openFile(sourceInfo); - return openResult; - } catch (IOException ex) { - View.showMessageDialog(null, AppStrings.translate("open.error.cannotOpen"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); - return OpenFileResult.ERROR; - } - } - - public static OpenFileResult openFile(SWFSourceInfo sourceInfo) { - return openFile(new SWFSourceInfo[]{sourceInfo}); - } - - public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { - return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen); - } - - public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos) { - return openFile(newSourceInfos, null); - } - - public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen) { - if (mainFrame != null && !Configuration.openMultipleFiles.get()) { - sourceInfos.clear(); - mainFrame.getPanel().closeAll(); - mainFrame.setVisible(false); - Helper.freeMem(); - } - - loadingDialog.setVisible(true); - OpenFileWorker wrk = new OpenFileWorker(newSourceInfos, executeAfterOpen); - wrk.execute(); - sourceInfos.addAll(Arrays.asList(newSourceInfos)); - return OpenFileResult.OK; - } - - public static void closeFile(SWFList swf) { - sourceInfos.remove(swf.sourceInfo); - mainFrame.getPanel().close(swf); - } - - public static void closeAll() { - sourceInfos.clear(); - mainFrame.getPanel().closeAll(); - } - - public static boolean saveFileDialog(SWF swf, final SaveFileMode mode) { - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get())); - String ext = ".swf"; - switch (mode) { - case SAVE: - case SAVEAS: - if (swf.getFile() != null) { - ext = Path.getExtension(swf.getFile()); - } - break; - case EXE: - ext = ".exe"; - break; - } - final String extension = ext; - FileFilter swfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.swf"); - } - }; - - FileFilter exeFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".exe")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.exe"); - } - }; - if (mode == SaveFileMode.EXE) { - fc.setFileFilter(exeFilter); - } else if (!swf.gfx) { - fc.setFileFilter(swfFilter); - } else { - fc.addChoosableFileFilter(swfFilter); - } - FileFilter gfxFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.gfx"); - } - }; - if (mode == SaveFileMode.SAVE || mode == SaveFileMode.SAVEAS) { - if (swf.gfx) { - fc.setFileFilter(gfxFilter); - } else { - fc.addChoosableFileFilter(gfxFilter); - } - } - fc.setAcceptAllFileFilterUsed(false); - JFrame f = new JFrame(); - View.setWindowIcon(f); - if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) { - File file = Helper.fixDialogFile(fc.getSelectedFile()); - FileFilter selFilter = fc.getFileFilter(); - try { - String fileName = file.getAbsolutePath(); - if (selFilter == swfFilter) { - if (!fileName.toLowerCase().endsWith(extension)) { - fileName += extension; - } - swf.gfx = false; - } - if (selFilter == gfxFilter) { - if (!fileName.toLowerCase().endsWith(".gfx")) { - fileName += ".gfx"; - } - swf.gfx = true; - } - Main.saveFile(swf, fileName, mode); - Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath()); - return true; - } catch (IOException ex) { - View.showMessageDialog(null, AppStrings.translate("error.file.write")); - } - } - return false; - } - - public static boolean openFileDialog() { - JFileChooser fc = new JFileChooser(); - if (Configuration.openMultipleFiles.get()) { - fc.setMultiSelectionEnabled(true); - } - fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); - FileFilter allSupportedFilter = new FileFilter() { - private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip"}; - - @Override - public boolean accept(File f) { - String name = f.getName().toLowerCase(); - for (String ext : supportedExtensions) { - if (name.endsWith(ext)) { - return true; - } - } - return f.isDirectory(); - } - - @Override - public String getDescription() { - String exts = Helper.joinStrings(supportedExtensions, "*%s", "; "); - return AppStrings.translate("filter.supported") + " (" + exts + ")"; - } - }; - fc.setFileFilter(allSupportedFilter); - FileFilter swfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.swf"); - } - }; - fc.addChoosableFileFilter(swfFilter); - - FileFilter swcFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".swc")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.swc"); - } - }; - fc.addChoosableFileFilter(swcFilter); - - FileFilter gfxFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.gfx"); - } - }; - fc.addChoosableFileFilter(gfxFilter); - - FileFilter zipFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".zip")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.zip"); - } - }; - fc.addChoosableFileFilter(zipFilter); - - FileFilter binaryFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return true; - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.binary"); - } - }; - fc.addChoosableFileFilter(binaryFilter); - - fc.setAcceptAllFileFilterUsed(false); - JFrame f = new JFrame(); - View.setWindowIcon(f); - int returnVal = fc.showOpenDialog(f); - if (returnVal == JFileChooser.APPROVE_OPTION) { - Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); - File[] selFiles = fc.getSelectedFiles(); - for (File file : selFiles) { - File selfile = Helper.fixDialogFile(file); - Main.openFile(selfile.getAbsolutePath(), null); - } - return true; - } else { - return false; - } - } - - public static void displayErrorFrame() { - ErrorLogFrame.getInstance().setVisible(true); - } - - private static void initGui() { - if (GraphicsEnvironment.isHeadless()) { - System.err.println("Error: Your system does not support Graphic User Interface"); - exit(); - } - if (Configuration.useRibbonInterface.get()) { - View.setLookAndFeel(); - } else { - try { - UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, null); - UIManager.put("Tree.expandedIcon", null); - UIManager.put("Tree.collapsedIcon", null); - UIManager.put("ColorChooserUI", null); - UIManager.put("ColorChooser.swatchesRecentSwatchSize", null); - UIManager.put("ColorChooser.swatchesSwatchSize", null); - UIManager.put("RibbonApplicationMenuPopupPanelUI", null); - UIManager.put("RibbonApplicationMenuButtonUI", null); - UIManager.put("ProgressBarUI", null); - UIManager.put("TextField.background", null); - UIManager.put("FormattedTextField.background", null); - UIManager.put("CommandButtonUI", null); - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - ErrorLogFrame.createNewInstance(); - - autoCheckForUpdates(); - offerAssociation(); - loadingDialog = new LoadingDialog(); - } - - public static void showModeFrame() { - ensureMainFrame(); - mainFrame.setVisible(true); - } - - private static void offerAssociation() { - boolean offered = Configuration.offeredAssociation.get(); - if (!offered) { - if (Platform.isWindows()) { - if ((!ContextMenuTools.isAddedToContextMenu()) && View.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { - ContextMenuTools.addToContextMenu(true, false); - } - } - - Configuration.offeredAssociation.set(true); - } - } - - public static void initLang() { - if (GraphicsEnvironment.isHeadless()) { //No GUI in OS - return; - } - if (!Configuration.locale.hasValue()) { - if (Platform.isWindows()) { - //Load from Installer - String uninstKey = "{E618D276-6596-41F4-8A98-447D442A77DB}_is1"; - uninstKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uninstKey; - try { - if (Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey)) { - if (Advapi32Util.registryValueExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language")) { - String installedLoc = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language"); - int lcid = Integer.parseInt(installedLoc); - char buf[] = new char[9]; - int cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO639LANGNAME, buf, 9); - String langCode = new String(buf, 0, cnt).trim().toLowerCase(); - - cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO3166CTRYNAME, buf, 9); - String countryCode = new String(buf, 0, cnt).trim().toLowerCase(); - - List langs = Arrays.asList(SelectLanguageDialog.getAvailableLanguages()); - for (int i = 0; i < langs.size(); i++) { - langs.set(i, langs.get(i).toLowerCase()); - } - - String selectedLang = null; - - if (langs.contains(langCode + "-" + countryCode)) { - selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode + "-" + countryCode)]; - } else if (langs.contains(langCode)) { - selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode)]; - } - if (selectedLang != null) { - Configuration.locale.set(selectedLang); - } - } - } - } catch (Exception ex) { - //ignore - } - } - } - Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get())); - AppStrings.updateLanguage(); - - try { - Class cl = Class.forName("org.pushingpixels.substance.api.SubstanceLookAndFeel"); - Field field = cl.getDeclaredField("LABEL_BUNDLE"); - field.setAccessible(true); - field.set(null, null); - } catch (Throwable ex) { - logger.log(Level.SEVERE, null, ex); - } - - UIManager.put("OptionPane.okButtonText", AppStrings.translate("button.ok")); - UIManager.put("OptionPane.yesButtonText", AppStrings.translate("button.yes")); - UIManager.put("OptionPane.noButtonText", AppStrings.translate("button.no")); - UIManager.put("OptionPane.cancelButtonText", AppStrings.translate("button.cancel")); - UIManager.put("OptionPane.messageDialogTitle", AppStrings.translate("dialog.message.title")); - UIManager.put("OptionPane.titleText", AppStrings.translate("dialog.select.title")); - - UIManager.put("FileChooser.acceptAllFileFilterText", AppStrings.translate("FileChooser.acceptAllFileFilterText")); - UIManager.put("FileChooser.lookInLabelText", AppStrings.translate("FileChooser.lookInLabelText")); - UIManager.put("FileChooser.cancelButtonText", AppStrings.translate("button.cancel")); - UIManager.put("FileChooser.cancelButtonToolTipText", AppStrings.translate("button.cancel")); - UIManager.put("FileChooser.openButtonText", AppStrings.translate("FileChooser.openButtonText")); - UIManager.put("FileChooser.openButtonToolTipText", AppStrings.translate("FileChooser.openButtonToolTipText")); - UIManager.put("FileChooser.filesOfTypeLabelText", AppStrings.translate("FileChooser.filesOfTypeLabelText")); - UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); - UIManager.put("FileChooser.listViewButtonToolTipText", AppStrings.translate("FileChooser.listViewButtonToolTipText")); - UIManager.put("FileChooser.listViewButtonAccessibleName", AppStrings.translate("FileChooser.listViewButtonAccessibleName")); - UIManager.put("FileChooser.detailsViewButtonToolTipText", AppStrings.translate("FileChooser.detailsViewButtonToolTipText")); - UIManager.put("FileChooser.detailsViewButtonAccessibleName", AppStrings.translate("FileChooser.detailsViewButtonAccessibleName")); - UIManager.put("FileChooser.upFolderToolTipText", AppStrings.translate("FileChooser.upFolderToolTipText")); - UIManager.put("FileChooser.upFolderAccessibleName", AppStrings.translate("FileChooser.upFolderAccessibleName")); - UIManager.put("FileChooser.homeFolderToolTipText", AppStrings.translate("FileChooser.homeFolderToolTipText")); - UIManager.put("FileChooser.homeFolderAccessibleName", AppStrings.translate("FileChooser.homeFolderAccessibleName")); - UIManager.put("FileChooser.fileNameHeaderText", AppStrings.translate("FileChooser.fileNameHeaderText")); - UIManager.put("FileChooser.fileSizeHeaderText", AppStrings.translate("FileChooser.fileSizeHeaderText")); - UIManager.put("FileChooser.fileTypeHeaderText", AppStrings.translate("FileChooser.fileTypeHeaderText")); - UIManager.put("FileChooser.fileDateHeaderText", AppStrings.translate("FileChooser.fileDateHeaderText")); - UIManager.put("FileChooser.fileAttrHeaderText", AppStrings.translate("FileChooser.fileAttrHeaderText")); - UIManager.put("FileChooser.openDialogTitleText", AppStrings.translate("FileChooser.openDialogTitleText")); - UIManager.put("FileChooser.directoryDescriptionText", AppStrings.translate("FileChooser.directoryDescriptionText")); - UIManager.put("FileChooser.directoryOpenButtonText", AppStrings.translate("FileChooser.directoryOpenButtonText")); - UIManager.put("FileChooser.directoryOpenButtonToolTipText", AppStrings.translate("FileChooser.directoryOpenButtonToolTipText")); - UIManager.put("FileChooser.fileDescriptionText", AppStrings.translate("FileChooser.fileDescriptionText")); - UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); - UIManager.put("FileChooser.helpButtonText", AppStrings.translate("FileChooser.helpButtonText")); - UIManager.put("FileChooser.helpButtonToolTipText", AppStrings.translate("FileChooser.helpButtonToolTipText")); - UIManager.put("FileChooser.newFolderAccessibleName", AppStrings.translate("FileChooser.newFolderAccessibleName")); - UIManager.put("FileChooser.newFolderErrorText", AppStrings.translate("FileChooser.newFolderErrorText")); - UIManager.put("FileChooser.newFolderToolTipText", AppStrings.translate("FileChooser.newFolderToolTipText")); - UIManager.put("FileChooser.other.newFolder", AppStrings.translate("FileChooser.other.newFolder")); - UIManager.put("FileChooser.other.newFolder.subsequent", AppStrings.translate("FileChooser.other.newFolder.subsequent")); - UIManager.put("FileChooser.win32.newFolder", AppStrings.translate("FileChooser.win32.newFolder")); - UIManager.put("FileChooser.win32.newFolder.subsequent", AppStrings.translate("FileChooser.win32.newFolder.subsequent")); - UIManager.put("FileChooser.saveButtonText", AppStrings.translate("FileChooser.saveButtonText")); - UIManager.put("FileChooser.saveButtonToolTipText", AppStrings.translate("FileChooser.saveButtonToolTipText")); - UIManager.put("FileChooser.saveDialogTitleText", AppStrings.translate("FileChooser.saveDialogTitleText")); - UIManager.put("FileChooser.saveInLabelText", AppStrings.translate("FileChooser.saveInLabelText")); - UIManager.put("FileChooser.updateButtonText", AppStrings.translate("FileChooser.updateButtonText")); - UIManager.put("FileChooser.updateButtonToolTipText", AppStrings.translate("FileChooser.updateButtonToolTipText")); - - UIManager.put("FileChooser.detailsViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewActionLabel.textAndMnemonic")); - UIManager.put("FileChooser.detailsViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewButtonToolTip.textAndMnemonic")); - UIManager.put("FileChooser.fileAttrHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileAttrHeader.textAndMnemonic")); - UIManager.put("FileChooser.fileDateHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileDateHeader.textAndMnemonic")); - UIManager.put("FileChooser.fileNameHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileNameHeader.textAndMnemonic")); - UIManager.put("FileChooser.fileNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.fileNameLabel.textAndMnemonic")); - UIManager.put("FileChooser.fileSizeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileSizeHeader.textAndMnemonic")); - UIManager.put("FileChooser.fileTypeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileTypeHeader.textAndMnemonic")); - UIManager.put("FileChooser.filesOfTypeLabel.textAndMnemonic", AppStrings.translate("FileChooser.filesOfTypeLabel.textAndMnemonic")); - UIManager.put("FileChooser.folderNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.folderNameLabel.textAndMnemonic")); - UIManager.put("FileChooser.homeFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.homeFolderToolTip.textAndMnemonic")); - UIManager.put("FileChooser.listViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.listViewActionLabel.textAndMnemonic")); - UIManager.put("FileChooser.listViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.listViewButtonToolTip.textAndMnemonic")); - UIManager.put("FileChooser.lookInLabel.textAndMnemonic", AppStrings.translate("FileChooser.lookInLabel.textAndMnemonic")); - UIManager.put("FileChooser.newFolderActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.newFolderActionLabel.textAndMnemonic")); - UIManager.put("FileChooser.newFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.newFolderToolTip.textAndMnemonic")); - UIManager.put("FileChooser.refreshActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.refreshActionLabel.textAndMnemonic")); - UIManager.put("FileChooser.saveInLabel.textAndMnemonic", AppStrings.translate("FileChooser.saveInLabel.textAndMnemonic")); - UIManager.put("FileChooser.upFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.upFolderToolTip.textAndMnemonic")); - UIManager.put("FileChooser.viewMenuButtonAccessibleName", AppStrings.translate("FileChooser.viewMenuButtonAccessibleName")); - UIManager.put("FileChooser.viewMenuButtonToolTipText", AppStrings.translate("FileChooser.viewMenuButtonToolTipText")); - UIManager.put("FileChooser.viewMenuLabel.textAndMnemonic", AppStrings.translate("FileChooser.viewMenuLabel.textAndMnemonic")); - UIManager.put("FileChooser.newFolderActionLabelText", AppStrings.translate("FileChooser.newFolderActionLabelText")); - UIManager.put("FileChooser.listViewActionLabelText", AppStrings.translate("FileChooser.listViewActionLabelText")); - UIManager.put("FileChooser.detailsViewActionLabelText", AppStrings.translate("FileChooser.detailsViewActionLabelText")); - UIManager.put("FileChooser.refreshActionLabelText", AppStrings.translate("FileChooser.refreshActionLabelText")); - UIManager.put("FileChooser.sortMenuLabelText", AppStrings.translate("FileChooser.sortMenuLabelText")); - UIManager.put("FileChooser.viewMenuLabelText", AppStrings.translate("FileChooser.viewMenuLabelText")); - UIManager.put("FileChooser.fileSizeKiloBytes", AppStrings.translate("FileChooser.fileSizeKiloBytes")); - UIManager.put("FileChooser.fileSizeMegaBytes", AppStrings.translate("FileChooser.fileSizeMegaBytes")); - UIManager.put("FileChooser.fileSizeGigaBytes", AppStrings.translate("FileChooser.fileSizeGigaBytes")); - UIManager.put("FileChooser.folderNameLabelText", AppStrings.translate("FileChooser.folderNameLabelText")); - - UIManager.put("ColorChooser.okText", AppStrings.translate("ColorChooser.okText")); - UIManager.put("ColorChooser.cancelText", AppStrings.translate("ColorChooser.cancelText")); - UIManager.put("ColorChooser.resetText", AppStrings.translate("ColorChooser.resetText")); - UIManager.put("ColorChooser.previewText", AppStrings.translate("ColorChooser.previewText")); - UIManager.put("ColorChooser.swatchesNameText", AppStrings.translate("ColorChooser.swatchesNameText")); - UIManager.put("ColorChooser.swatchesRecentText", AppStrings.translate("ColorChooser.swatchesRecentText")); - UIManager.put("ColorChooser.sampleText", AppStrings.translate("ColorChooser.sampleText")); - - Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable"); - } - - /** - * Clear old FFDec/JavactiveX temp files - */ - private static void clearTemp() { - String tempDirPath = System.getProperty("java.io.tmpdir"); - if (tempDirPath == null) { - return; - } - File tempDir = new File(tempDirPath); - if (!tempDir.exists()) { - return; - } - File delFiles[] = tempDir.listFiles(new FilenameFilter() { - - @Override - public boolean accept(File dir, String name) { - return name.matches("ffdec_cache.*\\.tmp") || name.matches("javactivex_.*\\.exe") || name.matches("temp[0-9]+\\.swf") || name.matches("ffdec_view_.*\\.swf"); - } - }); - for (File f : delFiles) { - try { - f.delete(); - } catch (Exception ex) { - //ignore - } - } - } - - /** - * @param args the command line arguments - * @throws IOException On error - */ - public static void main(String[] args) throws IOException { - - clearTemp(); - String pluginPath = Configuration.pluginPath.get(); - if (pluginPath != null && !pluginPath.isEmpty()) { - try { - SWFDecompilerPlugin.loadPlugin(pluginPath); - } catch (Throwable e) { - View.showMessageDialog(null, "Failed to load plugin: " + pluginPath); - } - } - - AppStrings.setResourceClass(MainFrame.class); - initLogging(Configuration.debugMode.get()); - initLang(); - - if (Configuration.cacheOnDisk.get()) { - Cache.setStorageType(Cache.STORAGE_FILES); - } else { - Cache.setStorageType(Cache.STORAGE_MEMORY); - } - - if (args.length == 0) { - View.execInEventDispatch(() -> { - initGui(); - if (Configuration.allowOnlyOneInstance.get() && FirstInstance.focus()) { //Try to focus first instance - Main.exit(); - } else { - showModeFrame(); - reloadLastSession(); - } - }); - } else { - String[] filesToOpen = CommandLineArgumentParser.parseArguments(args); - if (filesToOpen != null && filesToOpen.length > 0) { - View.execInEventDispatch(() -> { - initGui(); - shouldCloseWhenClosingLoadingDialog = true; - if (Configuration.allowOnlyOneInstance.get() && FirstInstance.openFiles(Arrays.asList(filesToOpen))) { //Try to open in first instance - Main.exit(); - } else { - for (String fileToOpen : filesToOpen) { - openFile(fileToOpen, null); - } - } - }); - } - } - } - - private static void reloadLastSession() { - if (Configuration.saveSessionOnExit.get()) { - String lastSession = Configuration.lastSessionData.get(); - if (lastSession != null && lastSession.length() > 0) { - String[] filesToOpen = lastSession.split(File.pathSeparator, -1); - int cnt = filesToOpen.length - 1; - SWFSourceInfo[] sourceInfos = new SWFSourceInfo[cnt]; - for (int i = 0; i < cnt; i++) { - String fileToOpen = filesToOpen[i]; - sourceInfos[i] = new SWFSourceInfo(null, fileToOpen, null); - } - - openFile(sourceInfos, () -> { - // last part contains the selected node in the tagtree - String pathStr = filesToOpen[filesToOpen.length - 1]; - mainFrame.getPanel().tagTree.setSelectionPathString(pathStr); - }); - } - } - } - - public static String tempFile(String url) throws IOException { - File f = new File(Configuration.getFFDecHome() + "saved" + File.separator); - Path.createDirectorySafe(f); - return Configuration.getFFDecHome() + "saved" + File.separator + "asdec_" + Integer.toHexString(url.hashCode()) + ".tmp"; - } - - public static void removeTrayIcon() { - if (SystemTray.isSupported()) { - SystemTray tray = SystemTray.getSystemTray(); - if (trayIcon != null) { - tray.remove(trayIcon); - trayIcon = null; - } - } - } - - public static void switchProxy() { - proxyFrame.switchState(); - if (stopMenuItem != null) { - if (proxyFrame.isRunning()) { - stopMenuItem.setLabel(AppStrings.translate("proxy.stop")); - } else { - stopMenuItem.setLabel(AppStrings.translate("proxy.start")); - } - } - } - - public static void addTrayIcon() { - if (trayIcon != null) { - return; - } - if (SystemTray.isSupported()) { - SystemTray tray = SystemTray.getSystemTray(); - trayIcon = new TrayIcon(View.loadImage("proxy16"), ApplicationInfo.VENDOR + " " + ApplicationInfo.SHORT_APPLICATION_NAME + " " + AppStrings.translate("proxy")); - trayIcon.setImageAutoSize(true); - PopupMenu trayPopup = new PopupMenu(); - - ActionListener trayListener = new ActionListener() { - /** - * Invoked when an action occurs. - */ - @Override - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("EXIT")) { - Main.exit(); - } - if (e.getActionCommand().equals("SHOW")) { - Main.showProxy(); - } - if (e.getActionCommand().equals("SWITCH")) { - Main.switchProxy(); - } - } - }; - - MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show")); - showMenuItem.setActionCommand("SHOW"); - showMenuItem.addActionListener(trayListener); - trayPopup.add(showMenuItem); - stopMenuItem = new MenuItem(AppStrings.translate("proxy.start")); - stopMenuItem.setActionCommand("SWITCH"); - stopMenuItem.addActionListener(trayListener); - trayPopup.add(stopMenuItem); - trayPopup.addSeparator(); - MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit")); - exitMenuItem.setActionCommand("EXIT"); - exitMenuItem.addActionListener(trayListener); - trayPopup.add(exitMenuItem); - - trayIcon.setPopupMenu(trayPopup); - trayIcon.addMouseListener(new MouseAdapter() { - /** - * {@inheritDoc} - */ - @Override - public void mouseClicked(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON1) { - Main.showProxy(); - } - } - }); - try { - tray.add(trayIcon); - } catch (AWTException ex) { - } - } - } - - public static void exit() { - Configuration.saveConfig(); - if (mainFrame != null && mainFrame.getPanel() != null) { - mainFrame.getPanel().unloadFlashPlayer(); - } - System.exit(0); - } - - public static void about() { - (new AboutDialog()).setVisible(true); - } - - public static void advancedSettings() { - (new AdvancedSettingsDialog()).setVisible(true); - } - - public static void autoCheckForUpdates() { - if (Configuration.checkForUpdatesAuto.get()) { - Calendar lastUpdatesCheckDate = Configuration.lastUpdatesCheckDate.get(); - if ((lastUpdatesCheckDate == null) || (lastUpdatesCheckDate.getTime().getTime() < Calendar.getInstance().getTime().getTime() - Configuration.checkForUpdatesDelay.get())) { - new SwingWorker() { - @Override - protected Object doInBackground() throws Exception { - checkForUpdates(); - return null; - } - }.execute(); - } - } - } - - public static boolean checkForUpdates() { - String currentVersion = ApplicationInfo.version; - if (currentVersion.equals("unknown")) { - // sometimes during development the version information is not available - return false; - } - - List accepted = new ArrayList<>(); - if (Configuration.checkForUpdatesStable.get()) { - accepted.add("stable"); - } - if (Configuration.checkForUpdatesNightly.get()) { - accepted.add("nightly"); - } - - if (accepted.isEmpty()) { - return false; - } - - String acceptVersions = String.join(",", accepted); - try { - String proxyAddress = Configuration.updateProxyAddress.get(); - URL url = new URL(ApplicationInfo.updateCheckUrl); - - URLConnection uc = null; - if (proxyAddress != null && !proxyAddress.isEmpty()) { - int port = 8080; - if (proxyAddress.contains(":")) { - String[] parts = proxyAddress.split(":"); - port = Integer.parseInt(parts[1]); - proxyAddress = parts[0]; - } - - uc = url.openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, port))); - } else { - uc = url.openConnection(); - } - uc.setRequestProperty("X-Accept-Versions", acceptVersions); - uc.setRequestProperty("X-Update-Major", "" + UPDATE_SYSTEM_MAJOR); - uc.setRequestProperty("X-Update-Minor", "" + UPDATE_SYSTEM_MINOR); - uc.setRequestProperty("User-Agent", ApplicationInfo.shortApplicationVerName); - String currentLoc = Configuration.locale.get("en"); - uc.setRequestProperty("Accept-Language", currentLoc + ("en".equals(currentLoc) ? "" : ", en;q=0.8")); - - uc.connect(); - - BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream())); - String s; - final java.util.List versions = new ArrayList<>(); - String header = ""; - Pattern headerPat = Pattern.compile("\\[([a-zA-Z0-9]+)\\]"); - int updateMajor; - int updateMinor; - Version ver = null; - while ((s = br.readLine()) != null) { - - Matcher m = headerPat.matcher(s); - if (m.matches()) { - header = m.group(1); - if (header.equals("version")) { - ver = new Version(); - versions.add(ver); - } - if (header.equals("noversion")) { - break; - } - } else { - if (s.contains("=")) { - String key = s.substring(0, s.indexOf('=')); - String val = s.substring(s.indexOf('=') + 1); - if ("updateSystem".equals(header)) { - if (key.equals("majorVersion")) { - updateMajor = Integer.parseInt(val); - if (updateMajor > UPDATE_SYSTEM_MAJOR) { - break; - } - } - if (key.equals("minorVersion")) { - updateMinor = Integer.parseInt(val); - } - } - if ("version".equals(header) && (ver != null)) { - if (key.equals("versionId")) { - ver.versionId = Integer.parseInt(val); - } - if (key.equals("versionName")) { - ver.versionName = val; - } - if (key.equals("nightly")) { - ver.nightly = val.equals("true"); - } - if (key.equals("revision")) { - ver.revision = val; - } - if (key.equals("build")) { - ver.build = Integer.parseInt(val); - } - if (key.equals("major")) { - ver.major = Integer.parseInt(val); - } - if (key.equals("minor")) { - ver.minor = Integer.parseInt(val); - } - if (key.equals("release")) { - ver.release = Integer.parseInt(val); - } - if (key.equals("longVersionName")) { - ver.longVersionName = val; - } - if (key.equals("releaseDate")) { - ver.releaseDate = val; - } - if (key.equals("appName")) { - ver.appName = val; - } - if (key.equals("appFullName")) { - ver.appFullName = val; - } - if (key.equals("updateLink")) { - ver.updateLink = val; - } - if (key.equals("change[]")) { - String changeType = val.substring(0, val.indexOf('|')); - String change = val.substring(val.indexOf('|') + 1); - if (!ver.changes.containsKey(changeType)) { - ver.changes.put(changeType, new ArrayList<>()); - } - List chlist = ver.changes.get(changeType); - chlist.add(change); - } - } - } - } - } - - if (!versions.isEmpty()) { - View.execInEventDispatch(() -> { - NewVersionDialog newVersionDialog = new NewVersionDialog(versions); - newVersionDialog.setVisible(true); - Configuration.lastUpdatesCheckDate.set(Calendar.getInstance()); - }); - - return true; - } - } catch (IOException | NumberFormatException ex) { - return false; - } - Configuration.lastUpdatesCheckDate.set(Calendar.getInstance()); - return false; - } - - private static FileHandler fileTxt; - - public static void clearLogFile() { - Logger logger = Logger.getLogger(""); - - FileHandler oldFileTxt = fileTxt; - fileTxt = null; - if (oldFileTxt != null) { - logger.removeHandler(fileTxt); - oldFileTxt.flush(); - oldFileTxt.close(); - } - - String fileName; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss"); - - try { - fileName = Configuration.getFFDecHome() + File.separator + "logs" + File.separator; - if (Configuration.useDetailedLogging.get()) { - fileName += "log-" + sdf.format(new Date()) + ".txt"; - } else { - fileName += "log.txt"; - } - File f = new File(fileName).getParentFile(); - if (!f.exists()) { - f.mkdir(); - } - fileTxt = new FileHandler(fileName); - } catch (IOException | SecurityException ex) { - logger.log(Level.SEVERE, null, ex); - } - - Formatter formatterTxt = new LogFormatter(); - fileTxt.setFormatter(formatterTxt); - logger.addHandler(fileTxt); - - if (!GraphicsEnvironment.isHeadless() && ErrorLogFrame.hasInstance()) { - ErrorLogFrame.getInstance().clearErrorState(); - } - - sdf = new SimpleDateFormat("yyyy-MM-dd"); - logger.log(Level.INFO, "Date: {0}", sdf.format(new Date())); - logger.log(Level.INFO, ApplicationInfo.applicationVerName); - logger.log(Level.INFO, "{0} {1} {2}", new Object[]{ - System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")}); - logger.log(Level.INFO, "{0} {1} {2}", new Object[]{ - System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("os.arch")}); - } - - public static void initLogging(boolean debug) { - try { - Logger logger = Logger.getLogger(""); - logger.setLevel(Configuration.logLevel); - - Handler[] handlers = logger.getHandlers(); - for (int i = handlers.length - 1; i >= 0; i--) { - logger.removeHandler(handlers[i]); - } - - ConsoleHandler conHan = new ConsoleHandler(); - conHan.setLevel(debug ? Level.CONFIG : Level.WARNING); - SimpleFormatter formatterTxt = new SimpleFormatter(); - conHan.setFormatter(formatterTxt); - logger.addHandler(conHan); - clearLogFile(); - - } catch (Exception ex) { - throw new RuntimeException("Problems with creating the log files"); - } - } -} +/* + * Copyright (C) 2010-2015 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.ApplicationInfo; +import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFBundle; +import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.SearchMode; +import com.jpexs.decompiler.flash.SwfOpenException; +import com.jpexs.decompiler.flash.Version; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; +import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; +import com.jpexs.decompiler.flash.console.ContextMenuTools; +import com.jpexs.decompiler.flash.gui.pipes.FirstInstance; +import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.helpers.Cache; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.Path; +import com.jpexs.helpers.ProgressListener; +import com.jpexs.helpers.Stopwatch; +import com.jpexs.helpers.streams.SeekableInputStream; +import com.sun.jna.Platform; +import com.sun.jna.platform.win32.Advapi32Util; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinReg; +import java.awt.AWTException; +import java.awt.Frame; +import java.awt.GraphicsEnvironment; +import java.awt.MenuItem; +import java.awt.PopupMenu; +import java.awt.SystemTray; +import java.awt.TrayIcon; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Map.Entry; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.logging.ConsoleHandler; +import java.util.logging.FileHandler; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.SwingWorker; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.filechooser.FileFilter; +import org.pushingpixels.substance.api.SubstanceLookAndFeel; + +/** + * Main executable class + * + * @author JPEXS + */ +public class Main { + + protected static ProxyFrame proxyFrame; + + private static List sourceInfos = new ArrayList<>(); + + public static LoadingDialog loadingDialog; + + private static boolean working = false; + + private static TrayIcon trayIcon; + + private static MenuItem stopMenuItem; + + private static MainFrame mainFrame; + + public static final int UPDATE_SYSTEM_MAJOR = 1; + + public static final int UPDATE_SYSTEM_MINOR = 3; + + private static LoadFromMemoryFrame loadFromMemoryFrame; + + private static LoadFromCacheFrame loadFromCacheFrame; + + private static final Logger logger = Logger.getLogger(Main.class.getName()); + + public static DebugLogDialog debugDialog; + + public static boolean shouldCloseWhenClosingLoadingDialog; + + public static void ensureMainFrame() { + if (mainFrame == null) { + synchronized (Main.class) { + if (mainFrame == null) { + MainFrame frame; + if (Configuration.useRibbonInterface.get()) { + frame = new MainFrameRibbon(); + } else { + frame = new MainFrameClassic(); + } + frame.getPanel().setErrorState(ErrorLogFrame.getInstance().getErrorState()); + mainFrame = frame; + } + } + } + } + + public static MainFrame getMainFrame() { + return mainFrame; + } + + public static void loadFromCache() { + if (loadFromCacheFrame == null) { + loadFromCacheFrame = new LoadFromCacheFrame(); + } + loadFromCacheFrame.setVisible(true); + } + + public static void loadFromMemory() { + if (loadFromMemoryFrame == null) { + loadFromMemoryFrame = new LoadFromMemoryFrame(mainFrame); + } + loadFromMemoryFrame.setVisible(true); + } + + public static void setSubLimiter(boolean value) { + if (value) { + AVM2Code.toSourceLimit = Configuration.sublimiter.get(); + } else { + AVM2Code.toSourceLimit = -1; + } + } + + public static boolean isWorking() { + return working; + } + + public static void startProxy(int port) { + if (proxyFrame == null) { + proxyFrame = new ProxyFrame(mainFrame); + } + + proxyFrame.setPort(port); + addTrayIcon(); + switchProxy(); + } + + public static void showProxy() { + if (proxyFrame == null) { + proxyFrame = new ProxyFrame(mainFrame); + } + proxyFrame.setVisible(true); + proxyFrame.setState(Frame.NORMAL); + } + + public static void startWork(String name) { + startWork(name, -1, null); + } + + public static void startWork(String name, int percent) { + startWork(name, percent, null); + } + + public static void startWork(String name, CancellableWorker worker) { + startWork(name, -1, worker); + } + + public static void startWork(final String name, final int percent, final CancellableWorker worker) { + working = true; + View.execInEventDispatchLater(() -> { + if (mainFrame != null) { + mainFrame.getPanel().setWorkStatus(name, worker); + if (percent == -1) { + mainFrame.getPanel().hidePercent(); + } else { + mainFrame.getPanel().setPercent(percent); + } + } + if (loadingDialog != null) { + loadingDialog.setDetail(name); + loadingDialog.setPercent(percent); + } + if (CommandLineArgumentParser.isCommandLineMode()) { + System.out.println(name); + } + }); + } + + public static void stopWork() { + working = false; + View.execInEventDispatchLater(() -> { + if (mainFrame != null) { + mainFrame.getPanel().setWorkStatus("", null); + } + if (loadingDialog != null) { + loadingDialog.setDetail(""); + } + }); + } + + public static SWFList parseSWF(SWFSourceInfo sourceInfo) throws Exception { + SWFList result = new SWFList(); + + InputStream inputStream = sourceInfo.getInputStream(); + SWFBundle bundle = null; + FileInputStream fis = null; + if (inputStream == null) { + inputStream = new BufferedInputStream(fis = new FileInputStream(sourceInfo.getFile())); + bundle = sourceInfo.getBundle(false, SearchMode.ALL); + logger.log(Level.INFO, "Load file: {0}", sourceInfo.getFile()); + } else if (inputStream instanceof SeekableInputStream + || inputStream instanceof BufferedInputStream) { + try { + inputStream.reset(); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + logger.log(Level.INFO, "Load stream: {0}", sourceInfo.getFileTitle()); + } + + Stopwatch sw = Stopwatch.startNew(); + if (bundle != null) { + result.bundle = bundle; + result.name = new File(sourceInfo.getFileTitleOrName()).getName(); + for (Entry streamEntry : bundle.getAll().entrySet()) { + InputStream stream = streamEntry.getValue(); + stream.reset(); + CancellableWorker worker = new CancellableWorker() { + @Override + public SWF doInBackground() throws Exception { + SWF swf = new SWF(stream, null, streamEntry.getKey(), new ProgressListener() { + @Override + public void progress(int p) { + startWork(AppStrings.translate("work.reading.swf"), p); + } + }, Configuration.parallelSpeedUp.get()); + return swf; + } + }; + loadingDialog.setWroker(worker); + worker.execute(); + + try { + result.add(worker.get()); + } catch (CancellationException ex) { + logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", streamEntry.getKey()); + } + } + } else { + InputStream fInputStream = inputStream; + CancellableWorker worker = new CancellableWorker() { + @Override + public SWF doInBackground() throws Exception { + SWF swf = new SWF(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle(), new ProgressListener() { + @Override + public void progress(int p) { + startWork(AppStrings.translate("work.reading.swf"), p); + } + }, Configuration.parallelSpeedUp.get()); + return swf; + } + }; + if (loadingDialog != null) { + loadingDialog.setWroker(worker); + } + worker.execute(); + + try { + result.add(worker.get()); + } catch (CancellationException ex) { + logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", sourceInfo.getFileTitleOrName()); + } + } + + if (fis != null) { + logger.log(Level.INFO, "File loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000)); + fis.close(); + } else { + logger.log(Level.INFO, "Stream loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000)); + } + + result.sourceInfo = sourceInfo; + for (SWF swf : result) { + logger.log(Level.INFO, ""); + logger.log(Level.INFO, "== File information =="); + logger.log(Level.INFO, "Size: {0}", Helper.formatFileSize(swf.fileSize)); + logger.log(Level.INFO, "Flash version: {0}", swf.version); + int width = (int) ((swf.displayRect.Xmax - swf.displayRect.Xmin) / SWF.unitDivisor); + int height = (int) ((swf.displayRect.Ymax - swf.displayRect.Ymin) / SWF.unitDivisor); + logger.log(Level.INFO, "Width: {0}", width); + logger.log(Level.INFO, "Height: {0}", height); + + swf.swfList = result; + swf.addEventListener(new EventListener() { + @Override + public void handleExportingEvent(String type, int index, int count, Object data) { + String text = AppStrings.translate("work.exporting"); + if (type != null && type.length() > 0) { + text += " " + type; + } + + startWork(text + " " + index + "/" + count + " " + data); + } + + @Override + public void handleExportedEvent(String type, int index, int count, Object data) { + String text = AppStrings.translate("work.exported"); + if (type != null && type.length() > 0) { + text += " " + type; + } + + startWork(text + " " + index + "/" + count + " " + data); + } + + @Override + public void handleEvent(String event, Object data) { + if (event.equals("exporting") || event.equals("exported")) { + throw new Error("Event is not supported by this handler."); + } + if (event.equals("getVariables")) { + startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); + } + if (event.equals("deobfuscate")) { + startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); + } + if (event.equals("rename")) { + startWork(AppStrings.translate("work.renaming") + "..." + (String) data); + } + } + }); + } + + return result; + } + + public static void saveFile(SWF swf, String outfile) throws IOException { + saveFile(swf, outfile, SaveFileMode.SAVE); + } + + public static void saveFile(SWF swf, String outfile, SaveFileMode mode) throws IOException { + if (mode == SaveFileMode.SAVEAS && !swf.swfList.isBundle()) { + swf.setFile(outfile); + swf.swfList.sourceInfo.setFile(outfile); + } + File outfileF = new File(outfile); + File tmpFile = new File(outfile + ".tmp"); + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(tmpFile))) { + if (mode == SaveFileMode.EXE) { + InputStream exeStream = View.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/Swf2Exe.bin"); + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = exeStream.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); + } + int width = swf.displayRect.Xmax - swf.displayRect.Xmin; + int height = swf.displayRect.Ymax - swf.displayRect.Ymin; + fos.write(width & 0xff); + fos.write((width >> 8) & 0xff); + fos.write((width >> 16) & 0xff); + fos.write((width >> 24) & 0xff); + fos.write(height & 0xff); + fos.write((height >> 8) & 0xff); + fos.write((height >> 16) & 0xff); + fos.write((height >> 24) & 0xff); + fos.write(Configuration.saveAsExeScaleMode.get()); + } + swf.saveTo(fos); + } + if (tmpFile.exists()) { + if (tmpFile.length() > 0) { + outfileF.delete(); + if (!tmpFile.renameTo(outfileF)) { + tmpFile.delete(); + throw new IOException("Cannot access " + outfile); + } + } else { + throw new IOException("Output is empty"); + } + } + } + + private static class OpenFileWorker extends SwingWorker { + + private final SWFSourceInfo[] sourceInfos; + + private final Runnable executeAfterOpen; + + public OpenFileWorker(SWFSourceInfo sourceInfo) { + this(sourceInfo, null); + } + + public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { + this.sourceInfos = new SWFSourceInfo[]{sourceInfo}; + this.executeAfterOpen = executeAfterOpen; + } + + public OpenFileWorker(SWFSourceInfo[] sourceInfos) { + this(sourceInfos, null); + } + + public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen) { + this.sourceInfos = sourceInfos; + this.executeAfterOpen = executeAfterOpen; + } + + @Override + protected Object doInBackground() throws Exception { + boolean first = true; + SWF firstSWF = null; + for (final SWFSourceInfo sourceInfo : sourceInfos) { + SWFList swfs = null; + try { + Main.startWork(AppStrings.translate("work.reading.swf") + "..."); + try { + swfs = parseSWF(sourceInfo); + } catch (ExecutionException ex) { + Throwable cause = ex.getCause(); + if (cause instanceof SwfOpenException) { + throw (SwfOpenException) cause; + } + + throw ex; + } + } catch (OutOfMemoryError ex) { + logger.log(Level.SEVERE, null, ex); + View.showMessageDialog(null, "Cannot load SWF file. Out of memory."); + continue; + } catch (SwfOpenException ex) { + logger.log(Level.SEVERE, null, ex); + View.showMessageDialog(null, ex.getMessage()); + continue; + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + View.showMessageDialog(null, "Cannot load SWF file."); + continue; + } + + final SWFList swfs1 = swfs; + final boolean first1 = first; + first = false; + if (firstSWF == null) { + firstSWF = swfs1.get(0); + } + + try { + View.execInEventDispatch(() -> { + Main.startWork(AppStrings.translate("work.creatingwindow") + "..."); + ensureMainFrame(); + mainFrame.getPanel().load(swfs1, first1); + }); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + loadingDialog.setVisible(false); + shouldCloseWhenClosingLoadingDialog = false; + + final SWF fswf = firstSWF; + View.execInEventDispatch(() -> { + if (mainFrame != null) { + mainFrame.setVisible(true); + } + + Main.stopWork(); + + if (mainFrame != null && Configuration.gotoMainClassOnStartup.get()) { + mainFrame.getPanel().gotoDocumentClass(fswf); + } + + if (mainFrame != null && fswf != null) { + SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(fswf.getShortFileName()); + if (swfConf != null) { + String pathStr = swfConf.lastSelectedPath; + mainFrame.getPanel().tagTree.setSelectionPathString(pathStr); + } + } + + if (executeAfterOpen != null) { + executeAfterOpen.run(); + } + }); + + return true; + } + } + + public static boolean reloadSWFs() { + CancellableWorker.cancelBackgroundThreads(); + if (Main.sourceInfos.isEmpty()) { + Helper.freeMem(); + showModeFrame(); + return true; + } else { + SWFSourceInfo[] sourceInfosCopy = new SWFSourceInfo[sourceInfos.size()]; + sourceInfos.toArray(sourceInfosCopy); + sourceInfos.clear(); + openFile(sourceInfosCopy); + return true; + } + } + + public static void reloadApp() { + if (debugDialog != null) { + debugDialog.setVisible(false); + debugDialog.dispose(); + debugDialog = null; + } + if (loadingDialog != null) { + synchronized (Main.class) { + if (loadingDialog != null) { + loadingDialog.setVisible(false); + loadingDialog.dispose(); + loadingDialog = null; + } + } + } + if (proxyFrame != null) { + proxyFrame.setVisible(false); + proxyFrame.dispose(); + proxyFrame = null; + } + if (loadFromMemoryFrame != null) { + loadFromMemoryFrame.setVisible(false); + loadFromMemoryFrame.dispose(); + loadFromMemoryFrame = null; + } + if (loadFromCacheFrame != null) { + loadFromCacheFrame.setVisible(false); + loadFromCacheFrame.dispose(); + loadFromCacheFrame = null; + } + if (mainFrame != null) { + mainFrame.setVisible(false); + mainFrame.getPanel().closeAll(); + mainFrame.dispose(); + mainFrame = null; + } + FontTag.reload(); + Cache.clearAll(); + initGui(); + reloadSWFs(); + } + + public static OpenFileResult openFile(String swfFile, String fileTitle) { + return openFile(swfFile, fileTitle, null); + } + + public static OpenFileResult openFile(String swfFile, String fileTitle, Runnable executeAfterOpen) { + try { + File file = new File(swfFile); + if (!file.exists()) { + View.showMessageDialog(null, AppStrings.translate("open.error.fileNotFound"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); + return OpenFileResult.NOT_FOUND; + } + swfFile = file.getCanonicalPath(); + Configuration.addRecentFile(swfFile); + SWFSourceInfo sourceInfo = new SWFSourceInfo(null, swfFile, fileTitle); + OpenFileResult openResult = openFile(sourceInfo); + return openResult; + } catch (IOException ex) { + View.showMessageDialog(null, AppStrings.translate("open.error.cannotOpen"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); + return OpenFileResult.ERROR; + } + } + + public static OpenFileResult openFile(SWFSourceInfo sourceInfo) { + return openFile(new SWFSourceInfo[]{sourceInfo}); + } + + public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { + return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen); + } + + public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos) { + return openFile(newSourceInfos, null); + } + + public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen) { + if (mainFrame != null && !Configuration.openMultipleFiles.get()) { + sourceInfos.clear(); + mainFrame.getPanel().closeAll(); + mainFrame.setVisible(false); + Helper.freeMem(); + } + + loadingDialog.setVisible(true); + OpenFileWorker wrk = new OpenFileWorker(newSourceInfos, executeAfterOpen); + wrk.execute(); + sourceInfos.addAll(Arrays.asList(newSourceInfos)); + return OpenFileResult.OK; + } + + public static void closeFile(SWFList swf) { + sourceInfos.remove(swf.sourceInfo); + mainFrame.getPanel().close(swf); + } + + public static void closeAll() { + sourceInfos.clear(); + mainFrame.getPanel().closeAll(); + } + + public static boolean saveFileDialog(SWF swf, final SaveFileMode mode) { + JFileChooser fc = new JFileChooser(); + fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get())); + String ext = ".swf"; + switch (mode) { + case SAVE: + case SAVEAS: + if (swf.getFile() != null) { + ext = Path.getExtension(swf.getFile()); + } + break; + case EXE: + ext = ".exe"; + break; + } + final String extension = ext; + FileFilter swfFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.swf"); + } + }; + + FileFilter exeFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".exe")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.exe"); + } + }; + if (mode == SaveFileMode.EXE) { + fc.setFileFilter(exeFilter); + } else if (!swf.gfx) { + fc.setFileFilter(swfFilter); + } else { + fc.addChoosableFileFilter(swfFilter); + } + FileFilter gfxFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.gfx"); + } + }; + if (mode == SaveFileMode.SAVE || mode == SaveFileMode.SAVEAS) { + if (swf.gfx) { + fc.setFileFilter(gfxFilter); + } else { + fc.addChoosableFileFilter(gfxFilter); + } + } + fc.setAcceptAllFileFilterUsed(false); + JFrame f = new JFrame(); + View.setWindowIcon(f); + if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) { + File file = Helper.fixDialogFile(fc.getSelectedFile()); + FileFilter selFilter = fc.getFileFilter(); + try { + String fileName = file.getAbsolutePath(); + if (selFilter == swfFilter) { + if (!fileName.toLowerCase().endsWith(extension)) { + fileName += extension; + } + swf.gfx = false; + } + if (selFilter == gfxFilter) { + if (!fileName.toLowerCase().endsWith(".gfx")) { + fileName += ".gfx"; + } + swf.gfx = true; + } + Main.saveFile(swf, fileName, mode); + Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath()); + return true; + } catch (IOException ex) { + View.showMessageDialog(null, AppStrings.translate("error.file.write")); + } + } + return false; + } + + public static boolean openFileDialog() { + JFileChooser fc = new JFileChooser(); + if (Configuration.openMultipleFiles.get()) { + fc.setMultiSelectionEnabled(true); + } + fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); + FileFilter allSupportedFilter = new FileFilter() { + private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip"}; + + @Override + public boolean accept(File f) { + String name = f.getName().toLowerCase(); + for (String ext : supportedExtensions) { + if (name.endsWith(ext)) { + return true; + } + } + return f.isDirectory(); + } + + @Override + public String getDescription() { + String exts = Helper.joinStrings(supportedExtensions, "*%s", "; "); + return AppStrings.translate("filter.supported") + " (" + exts + ")"; + } + }; + fc.setFileFilter(allSupportedFilter); + FileFilter swfFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.swf"); + } + }; + fc.addChoosableFileFilter(swfFilter); + + FileFilter swcFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".swc")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.swc"); + } + }; + fc.addChoosableFileFilter(swcFilter); + + FileFilter gfxFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.gfx"); + } + }; + fc.addChoosableFileFilter(gfxFilter); + + FileFilter zipFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".zip")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.zip"); + } + }; + fc.addChoosableFileFilter(zipFilter); + + FileFilter binaryFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return true; + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.binary"); + } + }; + fc.addChoosableFileFilter(binaryFilter); + + fc.setAcceptAllFileFilterUsed(false); + JFrame f = new JFrame(); + View.setWindowIcon(f); + int returnVal = fc.showOpenDialog(f); + if (returnVal == JFileChooser.APPROVE_OPTION) { + Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); + File[] selFiles = fc.getSelectedFiles(); + for (File file : selFiles) { + File selfile = Helper.fixDialogFile(file); + Main.openFile(selfile.getAbsolutePath(), null); + } + return true; + } else { + return false; + } + } + + public static void displayErrorFrame() { + ErrorLogFrame.getInstance().setVisible(true); + } + + private static void initGui() { + if (GraphicsEnvironment.isHeadless()) { + System.err.println("Error: Your system does not support Graphic User Interface"); + exit(); + } + if (Configuration.useRibbonInterface.get()) { + View.setLookAndFeel(); + } else { + try { + UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, null); + UIManager.put("Tree.expandedIcon", null); + UIManager.put("Tree.collapsedIcon", null); + UIManager.put("ColorChooserUI", null); + UIManager.put("ColorChooser.swatchesRecentSwatchSize", null); + UIManager.put("ColorChooser.swatchesSwatchSize", null); + UIManager.put("RibbonApplicationMenuPopupPanelUI", null); + UIManager.put("RibbonApplicationMenuButtonUI", null); + UIManager.put("ProgressBarUI", null); + UIManager.put("TextField.background", null); + UIManager.put("FormattedTextField.background", null); + UIManager.put("CommandButtonUI", null); + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + ErrorLogFrame.createNewInstance(); + + autoCheckForUpdates(); + offerAssociation(); + loadingDialog = new LoadingDialog(); + } + + public static void showModeFrame() { + ensureMainFrame(); + mainFrame.setVisible(true); + } + + private static void offerAssociation() { + boolean offered = Configuration.offeredAssociation.get(); + if (!offered) { + if (Platform.isWindows()) { + if ((!ContextMenuTools.isAddedToContextMenu()) && View.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { + ContextMenuTools.addToContextMenu(true, false); + } + } + + Configuration.offeredAssociation.set(true); + } + } + + public static void initLang() { + if (GraphicsEnvironment.isHeadless()) { //No GUI in OS + return; + } + if (!Configuration.locale.hasValue()) { + if (Platform.isWindows()) { + //Load from Installer + String uninstKey = "{E618D276-6596-41F4-8A98-447D442A77DB}_is1"; + uninstKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uninstKey; + try { + if (Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey)) { + if (Advapi32Util.registryValueExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language")) { + String installedLoc = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language"); + int lcid = Integer.parseInt(installedLoc); + char buf[] = new char[9]; + int cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO639LANGNAME, buf, 9); + String langCode = new String(buf, 0, cnt).trim().toLowerCase(); + + cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO3166CTRYNAME, buf, 9); + String countryCode = new String(buf, 0, cnt).trim().toLowerCase(); + + List langs = Arrays.asList(SelectLanguageDialog.getAvailableLanguages()); + for (int i = 0; i < langs.size(); i++) { + langs.set(i, langs.get(i).toLowerCase()); + } + + String selectedLang = null; + + if (langs.contains(langCode + "-" + countryCode)) { + selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode + "-" + countryCode)]; + } else if (langs.contains(langCode)) { + selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode)]; + } + if (selectedLang != null) { + Configuration.locale.set(selectedLang); + } + } + } + } catch (Exception ex) { + //ignore + } + } + } + Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get())); + AppStrings.updateLanguage(); + + try { + Class cl = Class.forName("org.pushingpixels.substance.api.SubstanceLookAndFeel"); + Field field = cl.getDeclaredField("LABEL_BUNDLE"); + field.setAccessible(true); + field.set(null, null); + } catch (Throwable ex) { + logger.log(Level.SEVERE, null, ex); + } + + UIManager.put("OptionPane.okButtonText", AppStrings.translate("button.ok")); + UIManager.put("OptionPane.yesButtonText", AppStrings.translate("button.yes")); + UIManager.put("OptionPane.noButtonText", AppStrings.translate("button.no")); + UIManager.put("OptionPane.cancelButtonText", AppStrings.translate("button.cancel")); + UIManager.put("OptionPane.messageDialogTitle", AppStrings.translate("dialog.message.title")); + UIManager.put("OptionPane.titleText", AppStrings.translate("dialog.select.title")); + + UIManager.put("FileChooser.acceptAllFileFilterText", AppStrings.translate("FileChooser.acceptAllFileFilterText")); + UIManager.put("FileChooser.lookInLabelText", AppStrings.translate("FileChooser.lookInLabelText")); + UIManager.put("FileChooser.cancelButtonText", AppStrings.translate("button.cancel")); + UIManager.put("FileChooser.cancelButtonToolTipText", AppStrings.translate("button.cancel")); + UIManager.put("FileChooser.openButtonText", AppStrings.translate("FileChooser.openButtonText")); + UIManager.put("FileChooser.openButtonToolTipText", AppStrings.translate("FileChooser.openButtonToolTipText")); + UIManager.put("FileChooser.filesOfTypeLabelText", AppStrings.translate("FileChooser.filesOfTypeLabelText")); + UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); + UIManager.put("FileChooser.listViewButtonToolTipText", AppStrings.translate("FileChooser.listViewButtonToolTipText")); + UIManager.put("FileChooser.listViewButtonAccessibleName", AppStrings.translate("FileChooser.listViewButtonAccessibleName")); + UIManager.put("FileChooser.detailsViewButtonToolTipText", AppStrings.translate("FileChooser.detailsViewButtonToolTipText")); + UIManager.put("FileChooser.detailsViewButtonAccessibleName", AppStrings.translate("FileChooser.detailsViewButtonAccessibleName")); + UIManager.put("FileChooser.upFolderToolTipText", AppStrings.translate("FileChooser.upFolderToolTipText")); + UIManager.put("FileChooser.upFolderAccessibleName", AppStrings.translate("FileChooser.upFolderAccessibleName")); + UIManager.put("FileChooser.homeFolderToolTipText", AppStrings.translate("FileChooser.homeFolderToolTipText")); + UIManager.put("FileChooser.homeFolderAccessibleName", AppStrings.translate("FileChooser.homeFolderAccessibleName")); + UIManager.put("FileChooser.fileNameHeaderText", AppStrings.translate("FileChooser.fileNameHeaderText")); + UIManager.put("FileChooser.fileSizeHeaderText", AppStrings.translate("FileChooser.fileSizeHeaderText")); + UIManager.put("FileChooser.fileTypeHeaderText", AppStrings.translate("FileChooser.fileTypeHeaderText")); + UIManager.put("FileChooser.fileDateHeaderText", AppStrings.translate("FileChooser.fileDateHeaderText")); + UIManager.put("FileChooser.fileAttrHeaderText", AppStrings.translate("FileChooser.fileAttrHeaderText")); + UIManager.put("FileChooser.openDialogTitleText", AppStrings.translate("FileChooser.openDialogTitleText")); + UIManager.put("FileChooser.directoryDescriptionText", AppStrings.translate("FileChooser.directoryDescriptionText")); + UIManager.put("FileChooser.directoryOpenButtonText", AppStrings.translate("FileChooser.directoryOpenButtonText")); + UIManager.put("FileChooser.directoryOpenButtonToolTipText", AppStrings.translate("FileChooser.directoryOpenButtonToolTipText")); + UIManager.put("FileChooser.fileDescriptionText", AppStrings.translate("FileChooser.fileDescriptionText")); + UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); + UIManager.put("FileChooser.helpButtonText", AppStrings.translate("FileChooser.helpButtonText")); + UIManager.put("FileChooser.helpButtonToolTipText", AppStrings.translate("FileChooser.helpButtonToolTipText")); + UIManager.put("FileChooser.newFolderAccessibleName", AppStrings.translate("FileChooser.newFolderAccessibleName")); + UIManager.put("FileChooser.newFolderErrorText", AppStrings.translate("FileChooser.newFolderErrorText")); + UIManager.put("FileChooser.newFolderToolTipText", AppStrings.translate("FileChooser.newFolderToolTipText")); + UIManager.put("FileChooser.other.newFolder", AppStrings.translate("FileChooser.other.newFolder")); + UIManager.put("FileChooser.other.newFolder.subsequent", AppStrings.translate("FileChooser.other.newFolder.subsequent")); + UIManager.put("FileChooser.win32.newFolder", AppStrings.translate("FileChooser.win32.newFolder")); + UIManager.put("FileChooser.win32.newFolder.subsequent", AppStrings.translate("FileChooser.win32.newFolder.subsequent")); + UIManager.put("FileChooser.saveButtonText", AppStrings.translate("FileChooser.saveButtonText")); + UIManager.put("FileChooser.saveButtonToolTipText", AppStrings.translate("FileChooser.saveButtonToolTipText")); + UIManager.put("FileChooser.saveDialogTitleText", AppStrings.translate("FileChooser.saveDialogTitleText")); + UIManager.put("FileChooser.saveInLabelText", AppStrings.translate("FileChooser.saveInLabelText")); + UIManager.put("FileChooser.updateButtonText", AppStrings.translate("FileChooser.updateButtonText")); + UIManager.put("FileChooser.updateButtonToolTipText", AppStrings.translate("FileChooser.updateButtonToolTipText")); + + UIManager.put("FileChooser.detailsViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewActionLabel.textAndMnemonic")); + UIManager.put("FileChooser.detailsViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewButtonToolTip.textAndMnemonic")); + UIManager.put("FileChooser.fileAttrHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileAttrHeader.textAndMnemonic")); + UIManager.put("FileChooser.fileDateHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileDateHeader.textAndMnemonic")); + UIManager.put("FileChooser.fileNameHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileNameHeader.textAndMnemonic")); + UIManager.put("FileChooser.fileNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.fileNameLabel.textAndMnemonic")); + UIManager.put("FileChooser.fileSizeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileSizeHeader.textAndMnemonic")); + UIManager.put("FileChooser.fileTypeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileTypeHeader.textAndMnemonic")); + UIManager.put("FileChooser.filesOfTypeLabel.textAndMnemonic", AppStrings.translate("FileChooser.filesOfTypeLabel.textAndMnemonic")); + UIManager.put("FileChooser.folderNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.folderNameLabel.textAndMnemonic")); + UIManager.put("FileChooser.homeFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.homeFolderToolTip.textAndMnemonic")); + UIManager.put("FileChooser.listViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.listViewActionLabel.textAndMnemonic")); + UIManager.put("FileChooser.listViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.listViewButtonToolTip.textAndMnemonic")); + UIManager.put("FileChooser.lookInLabel.textAndMnemonic", AppStrings.translate("FileChooser.lookInLabel.textAndMnemonic")); + UIManager.put("FileChooser.newFolderActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.newFolderActionLabel.textAndMnemonic")); + UIManager.put("FileChooser.newFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.newFolderToolTip.textAndMnemonic")); + UIManager.put("FileChooser.refreshActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.refreshActionLabel.textAndMnemonic")); + UIManager.put("FileChooser.saveInLabel.textAndMnemonic", AppStrings.translate("FileChooser.saveInLabel.textAndMnemonic")); + UIManager.put("FileChooser.upFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.upFolderToolTip.textAndMnemonic")); + UIManager.put("FileChooser.viewMenuButtonAccessibleName", AppStrings.translate("FileChooser.viewMenuButtonAccessibleName")); + UIManager.put("FileChooser.viewMenuButtonToolTipText", AppStrings.translate("FileChooser.viewMenuButtonToolTipText")); + UIManager.put("FileChooser.viewMenuLabel.textAndMnemonic", AppStrings.translate("FileChooser.viewMenuLabel.textAndMnemonic")); + UIManager.put("FileChooser.newFolderActionLabelText", AppStrings.translate("FileChooser.newFolderActionLabelText")); + UIManager.put("FileChooser.listViewActionLabelText", AppStrings.translate("FileChooser.listViewActionLabelText")); + UIManager.put("FileChooser.detailsViewActionLabelText", AppStrings.translate("FileChooser.detailsViewActionLabelText")); + UIManager.put("FileChooser.refreshActionLabelText", AppStrings.translate("FileChooser.refreshActionLabelText")); + UIManager.put("FileChooser.sortMenuLabelText", AppStrings.translate("FileChooser.sortMenuLabelText")); + UIManager.put("FileChooser.viewMenuLabelText", AppStrings.translate("FileChooser.viewMenuLabelText")); + UIManager.put("FileChooser.fileSizeKiloBytes", AppStrings.translate("FileChooser.fileSizeKiloBytes")); + UIManager.put("FileChooser.fileSizeMegaBytes", AppStrings.translate("FileChooser.fileSizeMegaBytes")); + UIManager.put("FileChooser.fileSizeGigaBytes", AppStrings.translate("FileChooser.fileSizeGigaBytes")); + UIManager.put("FileChooser.folderNameLabelText", AppStrings.translate("FileChooser.folderNameLabelText")); + + UIManager.put("ColorChooser.okText", AppStrings.translate("ColorChooser.okText")); + UIManager.put("ColorChooser.cancelText", AppStrings.translate("ColorChooser.cancelText")); + UIManager.put("ColorChooser.resetText", AppStrings.translate("ColorChooser.resetText")); + UIManager.put("ColorChooser.previewText", AppStrings.translate("ColorChooser.previewText")); + UIManager.put("ColorChooser.swatchesNameText", AppStrings.translate("ColorChooser.swatchesNameText")); + UIManager.put("ColorChooser.swatchesRecentText", AppStrings.translate("ColorChooser.swatchesRecentText")); + UIManager.put("ColorChooser.sampleText", AppStrings.translate("ColorChooser.sampleText")); + + Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable"); + } + + /** + * Clear old FFDec/JavactiveX temp files + */ + private static void clearTemp() { + String tempDirPath = System.getProperty("java.io.tmpdir"); + if (tempDirPath == null) { + return; + } + File tempDir = new File(tempDirPath); + if (!tempDir.exists()) { + return; + } + File delFiles[] = tempDir.listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return name.matches("ffdec_cache.*\\.tmp") || name.matches("javactivex_.*\\.exe") || name.matches("temp[0-9]+\\.swf") || name.matches("ffdec_view_.*\\.swf"); + } + }); + for (File f : delFiles) { + try { + f.delete(); + } catch (Exception ex) { + //ignore + } + } + } + + /** + * @param args the command line arguments + * @throws IOException On error + */ + public static void main(String[] args) throws IOException { + + clearTemp(); + String pluginPath = Configuration.pluginPath.get(); + if (pluginPath != null && !pluginPath.isEmpty()) { + try { + SWFDecompilerPlugin.loadPlugin(pluginPath); + } catch (Throwable e) { + View.showMessageDialog(null, "Failed to load plugin: " + pluginPath); + } + } + + AppStrings.setResourceClass(MainFrame.class); + initLogging(Configuration.debugMode.get()); + initLang(); + + if (Configuration.cacheOnDisk.get()) { + Cache.setStorageType(Cache.STORAGE_FILES); + } else { + Cache.setStorageType(Cache.STORAGE_MEMORY); + } + + if (args.length == 0) { + View.execInEventDispatch(() -> { + initGui(); + if (Configuration.allowOnlyOneInstance.get() && FirstInstance.focus()) { //Try to focus first instance + Main.exit(); + } else { + showModeFrame(); + reloadLastSession(); + } + }); + } else { + String[] filesToOpen = CommandLineArgumentParser.parseArguments(args); + if (filesToOpen != null && filesToOpen.length > 0) { + View.execInEventDispatch(() -> { + initGui(); + shouldCloseWhenClosingLoadingDialog = true; + if (Configuration.allowOnlyOneInstance.get() && FirstInstance.openFiles(Arrays.asList(filesToOpen))) { //Try to open in first instance + Main.exit(); + } else { + for (String fileToOpen : filesToOpen) { + openFile(fileToOpen, null); + } + } + }); + } + } + } + + private static void reloadLastSession() { + if (Configuration.saveSessionOnExit.get()) { + String lastSession = Configuration.lastSessionFiles.get(); + if (lastSession != null && lastSession.length() > 0) { + String[] filesToOpen = lastSession.split(File.pathSeparator, -1); + SWFSourceInfo[] sourceInfos = new SWFSourceInfo[filesToOpen.length]; + for (int i = 0; i < filesToOpen.length; i++) { + String fileToOpen = filesToOpen[i]; + sourceInfos[i] = new SWFSourceInfo(null, fileToOpen, null); + } + + openFile(sourceInfos, () -> { + mainFrame.getPanel().tagTree.setSelectionPathString(Configuration.lastSessionSelection.get()); + }); + } + } + } + + public static String tempFile(String url) throws IOException { + File f = new File(Configuration.getFFDecHome() + "saved" + File.separator); + Path.createDirectorySafe(f); + return Configuration.getFFDecHome() + "saved" + File.separator + "asdec_" + Integer.toHexString(url.hashCode()) + ".tmp"; + } + + public static void removeTrayIcon() { + if (SystemTray.isSupported()) { + SystemTray tray = SystemTray.getSystemTray(); + if (trayIcon != null) { + tray.remove(trayIcon); + trayIcon = null; + } + } + } + + public static void switchProxy() { + proxyFrame.switchState(); + if (stopMenuItem != null) { + if (proxyFrame.isRunning()) { + stopMenuItem.setLabel(AppStrings.translate("proxy.stop")); + } else { + stopMenuItem.setLabel(AppStrings.translate("proxy.start")); + } + } + } + + public static void addTrayIcon() { + if (trayIcon != null) { + return; + } + if (SystemTray.isSupported()) { + SystemTray tray = SystemTray.getSystemTray(); + trayIcon = new TrayIcon(View.loadImage("proxy16"), ApplicationInfo.VENDOR + " " + ApplicationInfo.SHORT_APPLICATION_NAME + " " + AppStrings.translate("proxy")); + trayIcon.setImageAutoSize(true); + PopupMenu trayPopup = new PopupMenu(); + + ActionListener trayListener = new ActionListener() { + /** + * Invoked when an action occurs. + */ + @Override + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("EXIT")) { + Main.exit(); + } + if (e.getActionCommand().equals("SHOW")) { + Main.showProxy(); + } + if (e.getActionCommand().equals("SWITCH")) { + Main.switchProxy(); + } + } + }; + + MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show")); + showMenuItem.setActionCommand("SHOW"); + showMenuItem.addActionListener(trayListener); + trayPopup.add(showMenuItem); + stopMenuItem = new MenuItem(AppStrings.translate("proxy.start")); + stopMenuItem.setActionCommand("SWITCH"); + stopMenuItem.addActionListener(trayListener); + trayPopup.add(stopMenuItem); + trayPopup.addSeparator(); + MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit")); + exitMenuItem.setActionCommand("EXIT"); + exitMenuItem.addActionListener(trayListener); + trayPopup.add(exitMenuItem); + + trayIcon.setPopupMenu(trayPopup); + trayIcon.addMouseListener(new MouseAdapter() { + /** + * {@inheritDoc} + */ + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1) { + Main.showProxy(); + } + } + }); + try { + tray.add(trayIcon); + } catch (AWTException ex) { + } + } + } + + public static void exit() { + Configuration.saveConfig(); + if (mainFrame != null && mainFrame.getPanel() != null) { + mainFrame.getPanel().unloadFlashPlayer(); + } + System.exit(0); + } + + public static void about() { + (new AboutDialog()).setVisible(true); + } + + public static void advancedSettings() { + (new AdvancedSettingsDialog()).setVisible(true); + } + + public static void autoCheckForUpdates() { + if (Configuration.checkForUpdatesAuto.get()) { + Calendar lastUpdatesCheckDate = Configuration.lastUpdatesCheckDate.get(); + if ((lastUpdatesCheckDate == null) || (lastUpdatesCheckDate.getTime().getTime() < Calendar.getInstance().getTime().getTime() - Configuration.checkForUpdatesDelay.get())) { + new SwingWorker() { + @Override + protected Object doInBackground() throws Exception { + checkForUpdates(); + return null; + } + }.execute(); + } + } + } + + public static boolean checkForUpdates() { + String currentVersion = ApplicationInfo.version; + if (currentVersion.equals("unknown")) { + // sometimes during development the version information is not available + return false; + } + + List accepted = new ArrayList<>(); + if (Configuration.checkForUpdatesStable.get()) { + accepted.add("stable"); + } + if (Configuration.checkForUpdatesNightly.get()) { + accepted.add("nightly"); + } + + if (accepted.isEmpty()) { + return false; + } + + String acceptVersions = String.join(",", accepted); + try { + String proxyAddress = Configuration.updateProxyAddress.get(); + URL url = new URL(ApplicationInfo.updateCheckUrl); + + URLConnection uc = null; + if (proxyAddress != null && !proxyAddress.isEmpty()) { + int port = 8080; + if (proxyAddress.contains(":")) { + String[] parts = proxyAddress.split(":"); + port = Integer.parseInt(parts[1]); + proxyAddress = parts[0]; + } + + uc = url.openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, port))); + } else { + uc = url.openConnection(); + } + uc.setRequestProperty("X-Accept-Versions", acceptVersions); + uc.setRequestProperty("X-Update-Major", "" + UPDATE_SYSTEM_MAJOR); + uc.setRequestProperty("X-Update-Minor", "" + UPDATE_SYSTEM_MINOR); + uc.setRequestProperty("User-Agent", ApplicationInfo.shortApplicationVerName); + String currentLoc = Configuration.locale.get("en"); + uc.setRequestProperty("Accept-Language", currentLoc + ("en".equals(currentLoc) ? "" : ", en;q=0.8")); + + uc.connect(); + + BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream())); + String s; + final java.util.List versions = new ArrayList<>(); + String header = ""; + Pattern headerPat = Pattern.compile("\\[([a-zA-Z0-9]+)\\]"); + int updateMajor; + int updateMinor; + Version ver = null; + while ((s = br.readLine()) != null) { + + Matcher m = headerPat.matcher(s); + if (m.matches()) { + header = m.group(1); + if (header.equals("version")) { + ver = new Version(); + versions.add(ver); + } + if (header.equals("noversion")) { + break; + } + } else { + if (s.contains("=")) { + String key = s.substring(0, s.indexOf('=')); + String val = s.substring(s.indexOf('=') + 1); + if ("updateSystem".equals(header)) { + if (key.equals("majorVersion")) { + updateMajor = Integer.parseInt(val); + if (updateMajor > UPDATE_SYSTEM_MAJOR) { + break; + } + } + if (key.equals("minorVersion")) { + updateMinor = Integer.parseInt(val); + } + } + if ("version".equals(header) && (ver != null)) { + if (key.equals("versionId")) { + ver.versionId = Integer.parseInt(val); + } + if (key.equals("versionName")) { + ver.versionName = val; + } + if (key.equals("nightly")) { + ver.nightly = val.equals("true"); + } + if (key.equals("revision")) { + ver.revision = val; + } + if (key.equals("build")) { + ver.build = Integer.parseInt(val); + } + if (key.equals("major")) { + ver.major = Integer.parseInt(val); + } + if (key.equals("minor")) { + ver.minor = Integer.parseInt(val); + } + if (key.equals("release")) { + ver.release = Integer.parseInt(val); + } + if (key.equals("longVersionName")) { + ver.longVersionName = val; + } + if (key.equals("releaseDate")) { + ver.releaseDate = val; + } + if (key.equals("appName")) { + ver.appName = val; + } + if (key.equals("appFullName")) { + ver.appFullName = val; + } + if (key.equals("updateLink")) { + ver.updateLink = val; + } + if (key.equals("change[]")) { + String changeType = val.substring(0, val.indexOf('|')); + String change = val.substring(val.indexOf('|') + 1); + if (!ver.changes.containsKey(changeType)) { + ver.changes.put(changeType, new ArrayList<>()); + } + List chlist = ver.changes.get(changeType); + chlist.add(change); + } + } + } + } + } + + if (!versions.isEmpty()) { + View.execInEventDispatch(() -> { + NewVersionDialog newVersionDialog = new NewVersionDialog(versions); + newVersionDialog.setVisible(true); + Configuration.lastUpdatesCheckDate.set(Calendar.getInstance()); + }); + + return true; + } + } catch (IOException | NumberFormatException ex) { + return false; + } + Configuration.lastUpdatesCheckDate.set(Calendar.getInstance()); + return false; + } + + private static FileHandler fileTxt; + + public static void clearLogFile() { + Logger logger = Logger.getLogger(""); + + FileHandler oldFileTxt = fileTxt; + fileTxt = null; + if (oldFileTxt != null) { + logger.removeHandler(fileTxt); + oldFileTxt.flush(); + oldFileTxt.close(); + } + + String fileName; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss"); + + try { + fileName = Configuration.getFFDecHome() + File.separator + "logs" + File.separator; + if (Configuration.useDetailedLogging.get()) { + fileName += "log-" + sdf.format(new Date()) + ".txt"; + } else { + fileName += "log.txt"; + } + File f = new File(fileName).getParentFile(); + if (!f.exists()) { + f.mkdir(); + } + fileTxt = new FileHandler(fileName); + } catch (IOException | SecurityException ex) { + logger.log(Level.SEVERE, null, ex); + } + + Formatter formatterTxt = new LogFormatter(); + fileTxt.setFormatter(formatterTxt); + logger.addHandler(fileTxt); + + if (!GraphicsEnvironment.isHeadless() && ErrorLogFrame.hasInstance()) { + ErrorLogFrame.getInstance().clearErrorState(); + } + + sdf = new SimpleDateFormat("yyyy-MM-dd"); + logger.log(Level.INFO, "Date: {0}", sdf.format(new Date())); + logger.log(Level.INFO, ApplicationInfo.applicationVerName); + logger.log(Level.INFO, "{0} {1} {2}", new Object[]{ + System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")}); + logger.log(Level.INFO, "{0} {1} {2}", new Object[]{ + System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("os.arch")}); + } + + public static void initLogging(boolean debug) { + try { + Logger logger = Logger.getLogger(""); + logger.setLevel(Configuration.logLevel); + + Handler[] handlers = logger.getHandlers(); + for (int i = handlers.length - 1; i >= 0; i--) { + logger.removeHandler(handlers[i]); + } + + ConsoleHandler conHan = new ConsoleHandler(); + conHan.setLevel(debug ? Level.CONFIG : Level.WARNING); + SimpleFormatter formatterTxt = new SimpleFormatter(); + conHan.setFormatter(formatterTxt); + logger.addHandler(conHan); + clearLogFile(); + + } catch (Exception ex) { + throw new RuntimeException("Problems with creating the log files"); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java index f0ee16ed8..c295b2566 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java @@ -120,20 +120,25 @@ public final class MainFrameRibbon extends AppRibbonFrame { public void windowClosing(WindowEvent e) { if (Configuration.saveSessionOnExit.get()) { StringBuilder sb = new StringBuilder(); + boolean first = true; for (SWFList swf : panel.getSwfs()) { + if (!first) { + sb.append(File.pathSeparator); + } + first = false; String file = swf.sourceInfo.getFile(); if (file != null) { sb.append(file); - sb.append(File.pathSeparator); } } + Configuration.lastSessionFiles.set(sb.toString()); + String path = panel.tagTree.getSelectionPathString(); if (path != null) { - sb.append(path); + Configuration.lastSessionSelection.set(path); } - Configuration.lastSessionData.set(sb.toString()); } boolean closeResult = panel.closeAll(); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index fe3faf22f..a18d8d83c 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2881,6 +2881,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } catch (CancellationException ex) { getABCPanel().decompiledTextArea.setText("// " + AppStrings.translate("work.canceled")); } catch (Exception ex) { + Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, "Error", ex); getABCPanel().decompiledTextArea.setText("// " + AppStrings.translate("decompilationError") + ": " + ex); } }); @@ -2888,6 +2889,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se }; worker.execute(); setSourceWorker = worker; + Main.startWork(translate("work.decompiling") + "...", worker); } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 64ff16596..b459941bd 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -741,11 +741,11 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex, null, pack.allABCs); - if (!packs.isEmpty()) { - oldSp = packs.get(0).getClassPath().toString(); - } + String oldSp = pack.getClassPath().toString(); + /*List packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex, null, pack.allABCs); + if (!packs.isEmpty()) { + + }*/ String as = decompiledTextArea.getText(); abc.replaceScriptPack(pack, as); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 4880a0d34..0d7e649ff 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -275,7 +275,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL Highlighting ch = Highlighting.searchPos(classHighlights, pos); int cindex = (int) ch.getProperties().index; ABC abc = getABC(); - type.setVal(abc.instance_info.get(cindex).getName(abc.constants).getNameWithNamespace(abc.constants, true)); + type.setVal(abc.instance_info.get(cindex).getName(abc.constants).getNameWithNamespace(abc.constants).toString()); return ch.startPos; } @@ -356,7 +356,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL traitIndex.setVal(j); classTrait.setVal(false); multinameIndex.setVal(tr.name_index); - currentType = ii.getName(a.constants).getNameWithNamespace(a.constants, true); + currentType = ii.getName(a.constants).getNameWithNamespace(a.constants).toString(); found = true; break loopi; } @@ -371,7 +371,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL traitIndex.setVal(j); classTrait.setVal(true); multinameIndex.setVal(tr.name_index); - currentType = ii.getName(a.constants).getNameWithNamespace(a.constants, true); + currentType = ii.getName(a.constants).getNameWithNamespace(a.constants).toString(); found = true; break loopi; } @@ -465,7 +465,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL for (int i = 1; i < abc.constants.constant_multiname.size(); i++) { Multiname m = abc.constants.constant_multiname.get(i); if (m != null) { - if (typeName.equals(m.getNameWithNamespace(abc.constants, true))) { + if (typeName.equals(m.getNameWithNamespace(abc.constants).toString())) { return i; } } @@ -520,7 +520,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL if (tm != null) { String name = ""; if (classIndex > -1) { - name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants, false); + name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants).toPrintableString(); } Trait currentTrait = null; @@ -571,7 +571,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL } currentMethodHighlight = null; currentTrait = null; - String name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants, false); + String name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants).toPrintableString(); currentTrait = getCurrentTrait(); isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex); if (currentTrait != null) { diff --git a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java index 109b909ca..21a398abd 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java @@ -1,179 +1,179 @@ -/* - * Copyright (C) 2010-2015 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui.abc; - -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.abc.usages.InsideClassMultinameUsage; -import com.jpexs.decompiler.flash.abc.usages.MethodMultinameUsage; -import com.jpexs.decompiler.flash.abc.usages.MultinameUsage; -import com.jpexs.decompiler.flash.abc.usages.TraitMultinameUsage; -import com.jpexs.decompiler.flash.gui.AppDialog; -import com.jpexs.decompiler.flash.gui.View; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Container; -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.List; -import javax.swing.JButton; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - -/** - * - * @author JPEXS - */ -public class UsageFrame extends AppDialog implements MouseListener { - - private final JButton gotoButton = new JButton(translate("button.goto")); - - private final JButton cancelButton = new JButton(translate("button.cancel")); - - private final JList usageList; - - private final UsageListModel usageListModel; - - private final ABCPanel abcPanel; - - public UsageFrame(ABC abc, int multinameIndex, ABCPanel abcPanel, boolean definitions) { - super(abcPanel.getMainPanel().getMainFrame().getWindow()); - this.abcPanel = abcPanel; - List usages = definitions ? abc.findMultinameDefinition(multinameIndex) : abc.findMultinameUsage(multinameIndex); - Multiname m = abc.constants.constant_multiname.get(multinameIndex); - if (m.namespace_index > 0 && abc.constants.constant_namespace.get(m.namespace_index).kind != Namespace.KIND_PRIVATE) { - for (ABCContainerTag at : abc.getAbcTags()) { - ABC a = at.getABC(); - if (a == abc) { - continue; - } - int mid = a.constants.getMultinameId(m, false); - if (mid > 0) { - usages.addAll(definitions ? a.findMultinameDefinition(mid) : a.findMultinameUsage(mid)); - } - } - } - usageListModel = new UsageListModel(); - for (MultinameUsage u : usages) { - usageListModel.addElement(u); - } - usageList = new JList<>(usageListModel); - usageList.setBackground(Color.white); - gotoButton.addActionListener(this::gotoButtonActionPerformed); - cancelButton.addActionListener(this::cancelButtonActionPerformed); - - JPanel buttonsPanel = new JPanel(); - buttonsPanel.setLayout(new FlowLayout()); - buttonsPanel.add(gotoButton); - buttonsPanel.add(cancelButton); - - usageList.addMouseListener(this); - Container cont = getContentPane(); - cont.setLayout(new BorderLayout()); - cont.add(new JScrollPane(usageList), BorderLayout.CENTER); - cont.add(buttonsPanel, BorderLayout.SOUTH); - setSize(400, 300); - setTitle((definitions ? translate("dialog.title.declaration") : translate("dialog.title")) + abc.constants.getMultiname(multinameIndex).getNameWithNamespace(abc.constants, false)); - View.centerScreen(this); - View.setWindowIcon(this); - } - - public static void gotoUsage(final ABCPanel abcPanel, final MultinameUsage usage) { - if (usage instanceof InsideClassMultinameUsage) { - final InsideClassMultinameUsage icu = (InsideClassMultinameUsage) usage; - - Runnable settrait = new Runnable() { - - @Override - public void run() { - abcPanel.decompiledTextArea.removeScriptListener(this); - abcPanel.decompiledTextArea.setClassIndex(icu.classIndex); - if (usage instanceof TraitMultinameUsage) { - TraitMultinameUsage tmu = (TraitMultinameUsage) usage; - int traitIndex; - if (tmu.parentTraitIndex > -1) { - traitIndex = tmu.parentTraitIndex; - } else { - traitIndex = tmu.traitIndex; - } - if (!tmu.isStatic) { - traitIndex += abcPanel.abc.class_info.get(tmu.classIndex).static_traits.traits.size(); - } - if (tmu instanceof MethodMultinameUsage) { - MethodMultinameUsage mmu = (MethodMultinameUsage) usage; - if (mmu.isInitializer == true) { - traitIndex = abcPanel.abc.class_info.get(mmu.classIndex).static_traits.traits.size() + abcPanel.abc.instance_info.get(mmu.classIndex).instance_traits.traits.size() + (mmu.isStatic ? 1 : 0); - } - } - abcPanel.decompiledTextArea.gotoTrait(traitIndex); - } - } - }; - - if (abcPanel.decompiledTextArea.getClassIndex() == icu.classIndex && abcPanel.abc == icu.abc) { - settrait.run(); - } else { - abcPanel.decompiledTextArea.addScriptListener(settrait); - abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.abc.instance_info.get(icu.classIndex).getName(abcPanel.abc.constants).getNameWithNamespace(abcPanel.abc.constants, false)); - } - } - } - - private void gotoUsage() { - if (usageList.getSelectedIndex() != -1) { - MultinameUsage usage = usageListModel.getUsage(usageList.getSelectedIndex()); - gotoUsage(abcPanel, usage); - } - } - - private void gotoButtonActionPerformed(ActionEvent evt) { - gotoUsage(); - setVisible(false); - } - - private void cancelButtonActionPerformed(ActionEvent evt) { - setVisible(false); - } - - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - gotoUsage(); - } - } - - @Override - public void mousePressed(MouseEvent e) { - } - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } -} +/* + * Copyright (C) 2010-2015 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.abc; + +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.abc.usages.InsideClassMultinameUsage; +import com.jpexs.decompiler.flash.abc.usages.MethodMultinameUsage; +import com.jpexs.decompiler.flash.abc.usages.MultinameUsage; +import com.jpexs.decompiler.flash.abc.usages.TraitMultinameUsage; +import com.jpexs.decompiler.flash.gui.AppDialog; +import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.List; +import javax.swing.JButton; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +/** + * + * @author JPEXS + */ +public class UsageFrame extends AppDialog implements MouseListener { + + private final JButton gotoButton = new JButton(translate("button.goto")); + + private final JButton cancelButton = new JButton(translate("button.cancel")); + + private final JList usageList; + + private final UsageListModel usageListModel; + + private final ABCPanel abcPanel; + + public UsageFrame(ABC abc, int multinameIndex, ABCPanel abcPanel, boolean definitions) { + super(abcPanel.getMainPanel().getMainFrame().getWindow()); + this.abcPanel = abcPanel; + List usages = definitions ? abc.findMultinameDefinition(multinameIndex) : abc.findMultinameUsage(multinameIndex); + Multiname m = abc.constants.constant_multiname.get(multinameIndex); + if (m.namespace_index > 0 && abc.constants.constant_namespace.get(m.namespace_index).kind != Namespace.KIND_PRIVATE) { + for (ABCContainerTag at : abc.getAbcTags()) { + ABC a = at.getABC(); + if (a == abc) { + continue; + } + int mid = a.constants.getMultinameId(m, false); + if (mid > 0) { + usages.addAll(definitions ? a.findMultinameDefinition(mid) : a.findMultinameUsage(mid)); + } + } + } + usageListModel = new UsageListModel(); + for (MultinameUsage u : usages) { + usageListModel.addElement(u); + } + usageList = new JList<>(usageListModel); + usageList.setBackground(Color.white); + gotoButton.addActionListener(this::gotoButtonActionPerformed); + cancelButton.addActionListener(this::cancelButtonActionPerformed); + + JPanel buttonsPanel = new JPanel(); + buttonsPanel.setLayout(new FlowLayout()); + buttonsPanel.add(gotoButton); + buttonsPanel.add(cancelButton); + + usageList.addMouseListener(this); + Container cont = getContentPane(); + cont.setLayout(new BorderLayout()); + cont.add(new JScrollPane(usageList), BorderLayout.CENTER); + cont.add(buttonsPanel, BorderLayout.SOUTH); + setSize(400, 300); + setTitle((definitions ? translate("dialog.title.declaration") : translate("dialog.title")) + abc.constants.getMultiname(multinameIndex).getNameWithNamespace(abc.constants).toPrintableString()); + View.centerScreen(this); + View.setWindowIcon(this); + } + + public static void gotoUsage(final ABCPanel abcPanel, final MultinameUsage usage) { + if (usage instanceof InsideClassMultinameUsage) { + final InsideClassMultinameUsage icu = (InsideClassMultinameUsage) usage; + + Runnable settrait = new Runnable() { + + @Override + public void run() { + abcPanel.decompiledTextArea.removeScriptListener(this); + abcPanel.decompiledTextArea.setClassIndex(icu.classIndex); + if (usage instanceof TraitMultinameUsage) { + TraitMultinameUsage tmu = (TraitMultinameUsage) usage; + int traitIndex; + if (tmu.parentTraitIndex > -1) { + traitIndex = tmu.parentTraitIndex; + } else { + traitIndex = tmu.traitIndex; + } + if (!tmu.isStatic) { + traitIndex += abcPanel.abc.class_info.get(tmu.classIndex).static_traits.traits.size(); + } + if (tmu instanceof MethodMultinameUsage) { + MethodMultinameUsage mmu = (MethodMultinameUsage) usage; + if (mmu.isInitializer == true) { + traitIndex = abcPanel.abc.class_info.get(mmu.classIndex).static_traits.traits.size() + abcPanel.abc.instance_info.get(mmu.classIndex).instance_traits.traits.size() + (mmu.isStatic ? 1 : 0); + } + } + abcPanel.decompiledTextArea.gotoTrait(traitIndex); + } + } + }; + + if (abcPanel.decompiledTextArea.getClassIndex() == icu.classIndex && abcPanel.abc == icu.abc) { + settrait.run(); + } else { + abcPanel.decompiledTextArea.addScriptListener(settrait); + abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.abc.instance_info.get(icu.classIndex).getName(abcPanel.abc.constants).getNameWithNamespace(abcPanel.abc.constants).toPrintableString()); + } + } + } + + private void gotoUsage() { + if (usageList.getSelectedIndex() != -1) { + MultinameUsage usage = usageListModel.getUsage(usageList.getSelectedIndex()); + gotoUsage(abcPanel, usage); + } + } + + private void gotoButtonActionPerformed(ActionEvent evt) { + gotoUsage(); + setVisible(false); + } + + private void cancelButtonActionPerformed(ActionEvent evt) { + setVisible(false); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + gotoUsage(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/debugger/DebuggerTools.java b/src/com/jpexs/decompiler/flash/gui/debugger/DebuggerTools.java index d519d6808..6a6abcf3f 100644 --- a/src/com/jpexs/decompiler/flash/gui/debugger/DebuggerTools.java +++ b/src/com/jpexs/decompiler/flash/gui/debugger/DebuggerTools.java @@ -93,7 +93,7 @@ public class DebuggerTools { ABC a = ct.getABC(); for (int i = 1; i < a.constants.constant_multiname.size(); i++) { Multiname m = a.constants.constant_multiname.get(i); - if ("trace".equals(m.getNameWithNamespace(a.constants, true))) { + if ("trace".equals(m.getNameWithNamespace(a.constants).toString())) { m.namespace_index = a.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, a.constants.getStringId(debuggerPkg, true)), 0, true); m.name_index = a.constants.getStringId(fname, true); ((Tag) ct).setModified(true); @@ -116,7 +116,7 @@ public class DebuggerTools { ABC a = ct.getABC(); for (int i = 1; i < a.constants.constant_multiname.size(); i++) { Multiname m = a.constants.constant_multiname.get(i); - String packageStr = m.getNameWithNamespace(a.constants, true); + String packageStr = m.getNameWithNamespace(a.constants).toString(); if (isDebuggerClass(packageStr, "debugTrace") || isDebuggerClass(packageStr, "debugAlert") || isDebuggerClass(packageStr, "debugSocket") diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index 9072a1c4a..806cce884 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -342,8 +342,12 @@ config.description.setFFDecVersionInExportedFont = When this setting is disabled config.name.gui.skin = User Interface Skin config.description.gui.skin = Look and feel skin -config.name.lastSessionData = Last session data -config.description.lastSessionData = Contains the opened files from the last session +config.name.lastSessionFiles = Last session files +config.description.lastSessionFiles = Contains the opened files from the last session + +config.name.lastSessionSelection = Last session selection +config.description.lastSessionSelection = Contains the selection from the last session + config.name.loopMedia = Loop sounds and sprites config.description.loopMedia = Automatically restarts the playing of the sounds and sprites From 16a48a6004ff34fb2a6a266011925f06621d4136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 7 Jun 2015 14:55:26 +0200 Subject: [PATCH 04/20] Fix opening nonexistent files on restoring last session --- src/com/jpexs/decompiler/flash/gui/Main.java | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index b8029c337..436254e21 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -1143,15 +1143,21 @@ public class Main { String lastSession = Configuration.lastSessionFiles.get(); if (lastSession != null && lastSession.length() > 0) { String[] filesToOpen = lastSession.split(File.pathSeparator, -1); - SWFSourceInfo[] sourceInfos = new SWFSourceInfo[filesToOpen.length]; + List exfiles = new ArrayList<>(); for (int i = 0; i < filesToOpen.length; i++) { - String fileToOpen = filesToOpen[i]; - sourceInfos[i] = new SWFSourceInfo(null, fileToOpen, null); + if (new File(filesToOpen[i]).exists()) { + exfiles.add(filesToOpen[i]); + } + } + SWFSourceInfo[] sourceInfos = new SWFSourceInfo[exfiles.size()]; + for (int i = 0; i < exfiles.size(); i++) { + sourceInfos[i] = new SWFSourceInfo(null, exfiles.get(i), null); + } + if (sourceInfos.length > 0) { + openFile(sourceInfos, () -> { + mainFrame.getPanel().tagTree.setSelectionPathString(Configuration.lastSessionSelection.get()); + }); } - - openFile(sourceInfos, () -> { - mainFrame.getPanel().tagTree.setSelectionPathString(Configuration.lastSessionSelection.get()); - }); } } } From bce2bb7fd3903759f2446e51869ce391d0b50549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 12 Jun 2015 12:10:53 +0200 Subject: [PATCH 05/20] AVM2 Deobfuscator stub (similar to ActionDeobfuscator) --- .../flash/abc/avm2/AVM2Deobfuscator.java | 482 ++++++++++++++++++ .../abc/avm2/AVM2DeobfuscatorSimple.java | 360 +++++++++++++ .../avm2/FixItemCounterTranslateStack.java | 59 +++ .../localregs/SetLocalTypeIns.java | 3 +- .../flash/abc/types/MethodBody.java | 9 +- .../jpexs/decompiler/graph/ScopeStack.java | 6 +- .../decompiler/graph/TranslateStack.java | 11 + 7 files changed, 922 insertions(+), 8 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java new file mode 100644 index 000000000..e057fb9d4 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java @@ -0,0 +1,482 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.flash.action.deobfuscation.*; +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.AVM2LocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.action.ActionLocalData; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.ReturnActionItem; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.swf4.ActionAdd; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionLess; +import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; +import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; +import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; +import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; +import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; +import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; +import com.jpexs.decompiler.flash.action.swf5.ActionLess2; +import com.jpexs.decompiler.flash.action.swf5.ActionModulo; +import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; +import com.jpexs.decompiler.flash.action.swf5.ActionReturn; +import com.jpexs.decompiler.flash.action.swf6.ActionGreater; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import java.io.IOException; +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * AVM2 Deobfuscator - FIXME!!! Not ready yet! + * + * @author JPEXS + */ +public class AVM2Deobfuscator extends AVM2DeobfuscatorSimple { + + private final int executionLimit = 30000; + + @Override + public void actionListParsed(ActionList actions, SWF swf) { + + } + + @Override + public void deobfuscate(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + removeZeroJumps(body.getCode(), body); + } + + private boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) { + AVM2Code code = body.getCode(); + if (code.code.size() == 0) { + return false; + } + System.err.println("============================================="); + for (int i = 0; i < code.code.size(); i++) { + ExecutionResult result = new ExecutionResult(); + System.err.println("Execute from " + i); + executeActions(classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result); + + if (result.idx != -1) { + int newIstructionCount = 1; // jump + if (!result.stack.isEmpty()) { + newIstructionCount++; + } + newIstructionCount += 2 * result.variables.size(); + + if (newIstructionCount * 2 < result.instructionsProcessed) { + AVM2Instruction target = code.code.get(result.idx); + AVM2Instruction prevAction = code.code.get(i); + + for (int variableName : result.variables.keySet()) { + Object value = result.variables.get(variableName); + /*ActionPush push = new ActionPush(variableName); + push.values.add(value);*/ + AVM2Instruction push = makePush(value, cpool); + + code.insertInstruction(i++, push); + push.offset = prevAction.offset; + + code.insertInstruction(i++, push); + prevAction = push; + + /*if (result.defines.contains(variableName)) { + //ActionDefineLocal defineLocal = new ActionDefineLocal(); + AVM2Instruction defineLocal = new AVM2Instruction(prevAction.offset, new SetLocalIns(), new int[]{}); + defineLocal.setAddress(prevAction.getAddress()); + code.addAction(i++, defineLocal); + prevAction = defineLocal; + } else { + ActionSetVariable setVariable = new ActionSetVariable(); + setVariable.setAddress(prevAction.getAddress()); + code.addAction(i++, setVariable); + prevAction = setVariable; + }*/ + AVM2Instruction setVariable = new AVM2Instruction(prevAction.offset, new SetLocalIns(), new int[]{}); + code.insertInstruction(i++, setVariable); + prevAction = setVariable; + } + + if (!result.stack.isEmpty()) { + //ActionPush push = new ActionPush(0); + //push.values.clear(); + long ofs = prevAction.offset; + for (GraphTargetItem graphTargetItem : result.stack) { + //DirectValueActionItem dv = (DirectValueActionItem) graphTargetItem; + //push.values.add(dv.value); + AVM2Instruction push = makePush(cpool, graphTargetItem); + push.offset = ofs; + code.insertInstruction(i++, push); + ofs += push.getBytes().length; + prevAction = push; + } + } + + //ctionJump jump = new ActionJump(0); + AVM2Instruction jump = new AVM2Instruction(prevAction.offset, new JumpIns(), new int[]{0}); + //jump.setAddress(prevAction.getAddress()); + jump.operands[0] = (int) (target.offset - jump.offset - jump.getBytes().length); + code.insertInstruction(i++, jump); + return true; + } + } + } + + return false; + } + + private AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool cpool, MethodBody body, boolean isStatic, int classIndex) { + AVM2LocalData localData = new AVM2LocalData(); + localData.isStatic = isStatic; + localData.classIndex = classIndex; + localData.localRegs = new HashMap<>(); + localData.scopeStack = new ScopeStack(); + localData.constants = cpool; + localData.methodInfo = abc.method_info; + localData.methodBody = body; + localData.abc = abc; + localData.localRegNames = new HashMap<>(); + localData.fullyQualifiedNames = new ArrayList<>(); + localData.parsedExceptions = new ArrayList<>(); + localData.finallyJumps = new HashMap<>(); + localData.ignoredSwitches = new HashMap<>(); + localData.ignoredSwitches2 = new ArrayList<>(); + localData.scriptIndex = scriptIndex; + localData.localRegAssignmentIps = new HashMap<>(); + localData.ip = 0; + localData.refs = new HashMap<>(); + localData.code = body.getCode(); + return localData; + } + + private void executeActions(int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result) { + List output = new ArrayList<>(); + AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex); + localData.localRegs.put(0, new NullAVM2Item(null));//this + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); + int instructionsProcessed = 0; + + try { + while (true) { + if (idx > endIdx) { + break; + } + + AVM2Instruction action = code.code.get(idx); + instructionsProcessed++; + + if (instructionsProcessed > executionLimit) { + break; + } + + /*if (action instanceof ActionDefineLocal) { + GraphTargetItem top = stack.pop(); + String variableName = stack.peek().getResult().toString(); + result.defines.add(variableName); + stack.push(top); + }*/ + if (action.definition instanceof GetLocalTypeIns) { + int regId = ((GetLocalTypeIns) action.definition).getRegisterId(action);//stack.peek().getResult().toString(); + if (!localData.localRegs.containsKey(regId)) { + break; + } + } + + /*if (action instanceof ActionCallFunction) { + String functionName = stack.pop().getResult().toString(); + long numArgs = EcmaScript.toUint32(stack.pop().getResult()); + if (numArgs == 0) { + if (fakeFunctions != null && fakeFunctions.containsKey(functionName)) { + stack.push(new DirectValueActionItem(fakeFunctions.get(functionName))); + } else { + break; + } + } else { + break; + } + } else { + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + }*/ + System.err.println("Translating " + action); + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + Class allowedDefs[] = new Class[]{ + PushByteIns.class, + PushShortIns.class, + PushIntIns.class, + PushDoubleIns.class, + PushStringIns.class, + PushNullIns.class, + PushUndefinedIns.class, + PushFalseIns.class, + PushTrueIns.class, + DupIns.class, + SwapIns.class, + AddIns.class, + AddIIns.class, + SubtractIns.class, + SubtractIIns.class, + ModuloIns.class, + MultiplyIns.class, + BitAndIns.class, + BitXorIns.class, + BitOrIns.class, + LShiftIns.class, + RShiftIns.class, + URShiftIns.class, + EqualsIns.class, + NotIns.class, + IfTypeIns.class, + JumpIns.class, + IncrementIns.class, + IncrementIIns.class, + DecrementIns.class, + DecrementIIns.class, + SetLocalTypeIns.class, + GetLocalTypeIns.class, + GreaterEqualsIns.class, + GreaterThanIns.class, + LessThanIns.class, + LessEqualsIns.class, + StrictEqualsIns.class, + IfTypeIns.class, + ReturnVoidIns.class, + ReturnValueIns.class, + NewFunctionIns.class, + PopIns.class, + PushScopeIns.class + }; + + InstructionDefinition def = action.definition; + + boolean ok = false; + for (Class s : allowedDefs) { + if (s.isAssignableFrom(def.getClass())) { + ok = true; + break; + } + } + if (!ok) { + System.err.println("Broken"); + break; + } + + + /*for (String variable : localData.variables.keySet()) { + System.out.println(Helper.byteArrToString(variable.getBytes())); + }*/ + idx++; + + if (action.definition instanceof JumpIns) { + + long address = action.offset + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); + if (idx == -1) { + throw new TranslateException("Jump target not found: " + address); + } + } + + if (action.definition instanceof IfTypeIns) { + if (EcmaScript.toBoolean(stack.pop().getResult())) { + long address = action.offset + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address); + if (idx == -1) { + throw new TranslateException("If target not found: " + address); + } + } + } + + if (/*localData.variables.size() == 1 && */stack.allItemsFixed()) { + result.idx = idx == code.code.size() ? idx - 1 : idx; + result.instructionsProcessed = instructionsProcessed; + result.variables.clear(); + for (int variableName : localData.localRegs.keySet()) { + Object value = localData.localRegs.get(variableName).getResult(); + result.variables.put(variableName, value); + } + result.stack.clear(); + result.stack.addAll(stack); + } + + if (action.definition instanceof ReturnValueIns) { + if (output.size() > 0) { + ReturnValueAVM2Item ret = (ReturnValueAVM2Item) output.get(output.size() - 1); + result.resultValue = ret.value.getResult(); + } + break; + } + + if (action.definition instanceof ReturnVoidIns) { + break; + } + } + } catch (EmptyStackException | TranslateException | InterruptedException ex) { + //ex.printStackTrace(); + } + } + + /*private Map getFakeFunctionResults(ActionList actions) { + + Map results = new HashMap<>(); + + for (int i = 0; i < actions.size(); i++) { + Action action = actions.get(i); + if (action instanceof ActionDefineFunction) { + ActionDefineFunction def = (ActionDefineFunction) action; + if (def.paramNames.isEmpty()) { + ExecutionResult result = new ExecutionResult(); + List lastActions = actions.getContainerLastActions(action); + int lastActionIdx = actions.indexOf(lastActions.get(0)); + executeActions(actions, i + 1, lastActionIdx, null, result, null); + if (result.resultValue != null) { + results.put(def.functionName, result.resultValue); + for (int j = i; j <= lastActionIdx; j++) { + actions.removeAction(i); + } + } + } + } + } + + return results; + } + + @Override + public byte[] proxyFileCatched(byte[] data) { + return null; + } + + @Override + public void swfParsed(SWF swf) { + } + + @Override + public void abcParsed(ABC abc, SWF swf) { + } + + @Override + public void methodBodyParsed(MethodBody body, SWF swf) { + }*/ + class ExecutionResult { + + public int idx = -1; + + public int instructionsProcessed = -1; + + //public ActionConstantPool constantPool; + public Map variables = new HashMap<>(); + + //public Set defines = new HashSet<>(); + public TranslateStack stack = new TranslateStack("?"); + + public ScopeStack scopeStack = new ScopeStack(); + + public Object resultValue; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java new file mode 100644 index 000000000..1e21be20b --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.AVM2LocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; +import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.FalseItem; +import com.jpexs.decompiler.graph.model.TrueItem; +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { + + private final int executionLimit = 30000; + + @Override + public void actionListParsed(ActionList actions, SWF swf) { + + } + + protected AVM2Instruction makePush(Object ovalue, AVM2ConstantPool cpool) { + if (ovalue instanceof Long) { + long value = (Long) ovalue; + if (value >= -128 && value <= 127) { + return new AVM2Instruction(0, new PushByteIns(), new int[]{(int) (long) value}); + } else if (value >= -32768 && value <= 32767) { + return new AVM2Instruction(0, new PushShortIns(), new int[]{((int) (long) value) & 0xffff}); + } else { + return new AVM2Instruction(0, new PushIntIns(), new int[]{cpool.getIntId(value, true)}); + } + } + if (ovalue instanceof Double) { + return new AVM2Instruction(0, new PushDoubleIns(), new int[]{cpool.getDoubleId((Double) ovalue, true)}); + } + if (ovalue instanceof String) { + return new AVM2Instruction(0, new PushStringIns(), new int[]{cpool.getStringId((String) ovalue, true)}); + } + if (ovalue instanceof Boolean) { + if ((Boolean) ovalue) { + return new AVM2Instruction(0, new PushTrueIns(), new int[]{}); + } + return new AVM2Instruction(0, new PushFalseIns(), new int[]{}); + } + if (ovalue instanceof Null) { + return new AVM2Instruction(0, new PushNullIns(), new int[]{}); + } + if (ovalue instanceof Undefined) { + return new AVM2Instruction(0, new PushUndefinedIns(), new int[]{}); + } + return null; + } + + protected AVM2Instruction makePush(AVM2ConstantPool cpool, GraphTargetItem graphTargetItem) { + AVM2Instruction ins = null; + if (graphTargetItem instanceof IntegerValueAVM2Item) { + IntegerValueAVM2Item iv = (IntegerValueAVM2Item) graphTargetItem; + return makePush(iv.value, cpool); + } else if (graphTargetItem instanceof FloatValueAVM2Item) { + FloatValueAVM2Item fv = (FloatValueAVM2Item) graphTargetItem; + return makePush(fv.value, cpool); + } else if (graphTargetItem instanceof StringAVM2Item) { + StringAVM2Item fv = (StringAVM2Item) graphTargetItem; + return makePush(fv.value, cpool); + } else if (graphTargetItem instanceof TrueItem) { + return makePush(Boolean.TRUE, cpool); + } else if (graphTargetItem instanceof FalseItem) { + return makePush(Boolean.FALSE, cpool); + } else if (graphTargetItem instanceof NullAVM2Item) { + return makePush(new Null(), cpool); + } else if (graphTargetItem instanceof UndefinedAVM2Item) { + return makePush(new Undefined(), cpool); + } else { + return null; + } + } + + private boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + AVM2Code code = body.getCode(); + if (code.code.size() == 0) { + return false; + } + System.err.println("====================================================="); + + for (int i = 0; i < code.code.size(); i++) { + ExecutionResult result = new ExecutionResult(); + System.err.println("Execute from " + i); + executeActions(code, i, code.code.size() - 1, result); + + if (result.idx != -1) { + int newIstructionCount = 1; // jump + if (!result.stack.isEmpty()) { + newIstructionCount += result.stack.size(); + } + + if (newIstructionCount < result.instructionsProcessed) { + AVM2Instruction target = code.code.get(result.idx); + AVM2Instruction prevAction = code.code.get(i); + + if (result.stack.isEmpty() && prevAction.definition instanceof JumpIns) { + prevAction.operands[0] = ((int) (target.getOffset() - prevAction.getOffset() - prevAction.getBytes().length)); + } else { + if (!result.stack.isEmpty()) { + for (GraphTargetItem graphTargetItem : result.stack) { + AVM2Instruction ins = makePush(cpool, graphTargetItem); + if (ins != null) { + code.insertInstruction(i++, ins); + } + prevAction = ins; + //DirectValueActionItem dv = (DirectValueActionItem) graphTargetItem; + //push.values.add(dv.value); + } + //push.setAddress(prevAction.getAddress()); + + } + + AVM2Instruction jump = new AVM2Instruction(0, new JumpIns(), new int[]{0}); + jump.offset = prevAction.offset; + jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length)); + code.insertInstruction(i++, jump); + } + + AVM2Instruction nextAction = code.code.size() > i ? code.code.get(i) : null; + + removeUnreachableActions(code, cpool, trait, minfo, body); + removeZeroJumps(code, body); + + if (nextAction != null) { + int nextIdx = code.code.indexOf(nextAction); + if (nextIdx < i) { + i = nextIdx; + } + } + } + } + } + + return false; + } + + protected void removeUnreachableActions(AVM2Code code, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + code.removeDeadCode(cpool, trait, minfo, body); + } + + protected boolean removeZeroJumps(AVM2Code actions, MethodBody body) { + boolean result = false; + for (int i = 0; i < actions.code.size(); i++) { + AVM2Instruction action = actions.code.get(i); + if (action.definition instanceof JumpIns && action.operands[0] == 0) { + actions.removeInstruction(i, body); + i--; + result = true; + } + } + return result; + } + + private void executeActions(AVM2Code code, int idx, int endIdx, ExecutionResult result) { + List output = new ArrayList<>(); + AVM2LocalData localData = new AVM2LocalData(); + + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); + int instructionsProcessed = 0; + + try { + while (true) { + if (idx > endIdx) { + break; + } + + if (instructionsProcessed > executionLimit) { + break; + } + + AVM2Instruction action = code.code.get(idx); + + /*System.out.print(action.getASMSource(actions, new ArrayList(), ScriptExportMode.PCODE)); + for (int j = 0; j < stack.size(); j++) { + System.out.print(" '" + stack.get(j).getResult() + "'"); + } + System.out.println();*/ + InstructionDefinition def = action.definition; + + Class allowedDefs[] = new Class[]{ + PushByteIns.class, + PushShortIns.class, + PushIntIns.class, + PushDoubleIns.class, + PushStringIns.class, + PushNullIns.class, + PushUndefinedIns.class, + PushFalseIns.class, + PushTrueIns.class, + DupIns.class, + SwapIns.class, + AddIns.class, + AddIIns.class, + SubtractIns.class, + SubtractIIns.class, + ModuloIns.class, + MultiplyIns.class, + BitAndIns.class, + BitXorIns.class, + BitOrIns.class, + LShiftIns.class, + RShiftIns.class, + URShiftIns.class, + EqualsIns.class, + NotIns.class, + IfTypeIns.class, + JumpIns.class + }; + + boolean ok = false; + for (Class s : allowedDefs) { + if (s.isAssignableFrom(def.getClass())) { + ok = true; + break; + } + } + if (!ok) { + break; + } + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + + idx++; + + if (def instanceof JumpIns) { + //ActionJump jump = (ActionJump) action; + long address = action.getOffset() + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address); + if (idx == -1) { + throw new TranslateException("Jump target not found: " + address); + } + } + + if (def instanceof IfTypeIns) { + //ActionIf aif = (ActionIf) action; + if (EcmaScript.toBoolean(stack.pop().getResult())) { + long address = action.offset + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); + if (idx == -1) { + throw new TranslateException("If target not found: " + address); + } + } + } + + instructionsProcessed++; + + if (stack.allItemsFixed()) { + result.idx = idx == code.code.size() ? idx - 1 : idx; + result.instructionsProcessed = instructionsProcessed; + result.stack.clear(); + result.stack.addAll(stack); + } + } + } catch (EmptyStackException | TranslateException | InterruptedException ex) { + } + } + + @Override + public byte[] proxyFileCatched(byte[] data) { + return null; + } + + @Override + public void swfParsed(SWF swf) { + } + + @Override + public void abcParsed(ABC abc, SWF swf) { + } + + @Override + public void methodBodyParsed(MethodBody body, SWF swf) { + + } + + public void deobfuscate(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + removeZeroJumps(body.getCode(), body); + } + + class ExecutionResult { + + public int idx = -1; + + public int instructionsProcessed = -1; + + public TranslateStack stack = new TranslateStack("?"); + + public Object resultValue; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java new file mode 100644 index 000000000..05f02f399 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateStack; + +/** + * + * @author JPEXS + */ +public class FixItemCounterTranslateStack extends TranslateStack { + + private int fixItemCount = Integer.MAX_VALUE; + + public FixItemCounterTranslateStack(String path) { + super(null); //null path => do not add PushItems + } + + @Override + public GraphTargetItem pop() { + GraphTargetItem result = super.pop(); + int itemCount = size(); + if (itemCount < fixItemCount) { + fixItemCount = itemCount; + } + return result; + } + + @Override + public synchronized GraphTargetItem remove(int index) { + if (index < fixItemCount) { + fixItemCount = index; + } + return super.remove(index); + } + + public boolean allItemsFixed() { + return size() <= fixItemCount; + } + + public int getFixItemCount() { + return fixItemCount; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java index 85895b8e5..57158d6a3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java @@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.NotCompileTimeItem; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateStack; import java.util.HashMap; @@ -116,7 +117,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S } //if(val.startsWith("catchscope ")) return; - //if(val.startsWith("newactivation()")) return; + //if(val.startsWith("newactivation()")) return; output.add(new SetLocalAVM2Item(ins, regId, value)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 390ab7a40..37aa626ce 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ABCInputStream; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscator; import com.jpexs.decompiler.flash.abc.avm2.CodeStats; import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -278,13 +279,9 @@ public final class MethodBody implements Cloneable { deobfuscated.markMappedOffsets(); //deobfuscated.inlineJumpExit(); if (Configuration.autoDeobfuscate.get()) { - try { - deobfuscated.removeTraps(constants, trait, method_info.get(this.method_info), b, abc, scriptIndex, classIndex, isStatic, path); - } catch (StackOverflowError ex) { - logger.log(Level.SEVERE, "Error during remove traps in " + path, ex); - } + AVM2Deobfuscator deo = new AVM2Deobfuscator(); + deo.deobfuscate(classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b); } - //deobfuscated.restoreControlFlow(constants, b); return b; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java index af1152907..bb5478932 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java @@ -22,5 +22,9 @@ import java.util.Stack; * * @author JPEXS */ -public class ScopeStack extends Stack { +public class ScopeStack extends TranslateStack { + + public ScopeStack() { + super("scope"); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java index cc68f15ea..72ca11740 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java @@ -39,6 +39,17 @@ public class TranslateStack extends Stack { return path; } + @Override + public synchronized GraphTargetItem get(int index) { + if (path != null) { + if (index >= this.size() || index < 0) { + Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attemp to Get item outside of bounds of stack", path); + return pop; + } + } + return super.get(index); + } + @Override public synchronized GraphTargetItem peek() { if (path != null) { From 244204859896eb7876b7bec64d75bbc35ea6e163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 12 Jun 2015 12:51:52 +0200 Subject: [PATCH 06/20] unused imports --- .../flash/abc/avm2/AVM2Deobfuscator.java | 47 ------------------- 1 file changed, 47 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java index e057fb9d4..c82ee8952 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java @@ -16,10 +16,7 @@ */ package com.jpexs.decompiler.flash.abc.avm2; -import com.jpexs.decompiler.flash.action.deobfuscation.*; -import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; @@ -70,65 +67,21 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.action.ActionListReader; -import com.jpexs.decompiler.flash.action.ActionLocalData; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.ReturnActionItem; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.swf4.ActionAdd; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionLess; -import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; -import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; -import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; -import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; -import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; -import com.jpexs.decompiler.flash.action.swf5.ActionLess2; -import com.jpexs.decompiler.flash.action.swf5.ActionModulo; -import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; -import com.jpexs.decompiler.flash.action.swf5.ActionReturn; -import com.jpexs.decompiler.flash.action.swf6.ActionGreater; import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.flash.ecma.Undefined; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateException; import com.jpexs.decompiler.graph.TranslateStack; -import java.io.IOException; import java.util.ArrayList; import java.util.EmptyStackException; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; /** * From cac19d6cb98300773b17f1fb8d7d201d4aff8cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 3 Jun 2015 10:10:44 +0200 Subject: [PATCH 07/20] =?UTF-8?q?Stack=20handling=20improved=20-=20no=20mo?= =?UTF-8?q?re=20StackEmptyException=20And/Or=20handling=20improved=20Prepr?= =?UTF-8?q?ocessor=20instructions=20introduced=20-=20=C2=A7=C2=A7pop,?= =?UTF-8?q?=C2=A7=C2=A7push...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/jsyntaxpane-0.9.5.jar | Bin 558178 -> 563622 bytes .../lexers/actionscript3_script.flex | 228 +- .../ffdec_lib/lexers/actionscript_script.flex | 212 +- .../src/com/jpexs/decompiler/flash/SWF.java | 2 +- .../decompiler/flash/abc/AVM2LocalData.java | 7 +- .../decompiler/flash/abc/avm2/AVM2Code.java | 15 +- .../flash/abc/avm2/graph/AVM2Graph.java | 167 +- .../avm2/instructions/arithmetic/NotIns.java | 98 +- .../avm2/instructions/jumps/IfFalseIns.java | 113 +- .../avm2/instructions/jumps/IfTrueIns.java | 112 +- .../localregs/SetLocalTypeIns.java | 268 +- .../avm2/instructions/other/SetSlotIns.java | 4 +- .../abc/avm2/instructions/stack/PopIns.java | 10 +- .../avm2/instructions/stack/PushFalseIns.java | 109 +- .../avm2/instructions/stack/PushTrueIns.java | 109 +- .../flash/abc/avm2/model/HasNextAVM2Item.java | 4 +- .../abc/avm2/model/IntegerValueAVM2Item.java | 11 +- .../abc/avm2/model/NewActivationAVM2Item.java | 5 +- .../abc/avm2/model/NumberValueAVM2Item.java | 17 +- .../flash/abc/avm2/model/SetSlotAVM2Item.java | 4 +- .../flash/abc/avm2/model/StringAVM2Item.java | 8 +- .../abc/avm2/model/operations/EqAVM2Item.java | 5 +- .../abc/avm2/model/operations/GeAVM2Item.java | 5 +- .../abc/avm2/model/operations/GtAVM2Item.java | 5 +- .../abc/avm2/model/operations/LeAVM2Item.java | 5 +- .../abc/avm2/model/operations/LtAVM2Item.java | 5 +- .../avm2/model/operations/NeqAVM2Item.java | 5 +- .../model/operations/StrictEqAVM2Item.java | 5 +- .../model/operations/StrictNeqAVM2Item.java | 5 +- .../parser/script/AVM2SourceGenerator.java | 15 +- .../avm2/parser/script/ActionScriptLexer.java | 4472 ++++++++-------- .../abc/avm2/parser/script/SymbolGroup.java | 12 +- .../abc/avm2/parser/script/SymbolType.java | 485 +- .../jpexs/decompiler/flash/action/Action.java | 2669 +++++----- .../decompiler/flash/action/ActionGraph.java | 974 ++-- .../flash/action/ActionListReader.java | 2022 +++---- .../deobfuscation/ActionDeobfuscator.java | 4 +- .../ActionDeobfuscatorSimple.java | 4 +- .../FixItemCounterTranslateStack.java | 13 +- .../action/model/DirectValueActionItem.java | 8 +- .../action/model/EnumerateActionItem.java | 8 +- .../action/model/operations/EqActionItem.java | 5 +- .../action/model/operations/GeActionItem.java | 5 +- .../action/model/operations/GtActionItem.java | 5 +- .../action/model/operations/Inverted.java | 6 +- .../action/model/operations/LeActionItem.java | 2 +- .../action/model/operations/LtActionItem.java | 5 +- .../model/operations/NeqActionItem.java | 2 +- .../model/operations/StrictEqActionItem.java | 2 +- .../model/operations/StrictNeqActionItem.java | 2 +- .../model/operations/StringEqActionItem.java | 2 +- .../model/operations/StringGeActionItem.java | 2 +- .../model/operations/StringGtActionItem.java | 2 +- .../model/operations/StringLeActionItem.java | 2 +- .../model/operations/StringLtActionItem.java | 2 +- .../model/operations/StringNeActionItem.java | 2 +- .../parser/script/ActionScriptLexer.java | 4671 ++++++++--------- .../parser/script/ActionSourceGenerator.java | 1600 +++--- .../action/parser/script/SymbolGroup.java | 12 +- .../action/parser/script/SymbolType.java | 445 +- .../flash/action/swf4/ActionNot.java | 5 +- .../flash/action/swf4/ActionPop.java | 9 +- .../flash/action/swf4/ActionPush.java | 31 +- .../flash/action/swf5/ActionEnumerate.java | 7 +- .../action/swf5/ActionPushDuplicate.java | 6 +- .../flash/action/swf6/ActionEnumerate2.java | 84 +- .../src/com/jpexs/decompiler/graph/Graph.java | 383 +- .../decompiler/graph/GraphSourceItem.java | 104 +- .../decompiler/graph/GraphTargetItem.java | 617 +-- .../jpexs/decompiler/graph/SimpleValue.java | 10 + .../decompiler/graph/SourceGenerator.java | 9 +- .../decompiler/graph/TranslateStack.java | 40 + .../decompiler/graph/model/DuplicateItem.java | 29 +- .../decompiler/graph/model/ExitItem.java | 9 +- .../decompiler/graph/model/FalseItem.java | 68 + .../jpexs/decompiler/graph/model/IfItem.java | 11 +- .../decompiler/graph/model/LogicalOpItem.java | 6 +- .../jpexs/decompiler/graph/model/NotItem.java | 14 +- .../jpexs/decompiler/graph/model/PopItem.java | 57 + .../decompiler/graph/model/PushItem.java | 67 + .../decompiler/graph/model/TrueItem.java | 31 +- .../decompiler/graph/model/UnaryOpItem.java | 2 - .../decompiler/flash/ActionScript2Test.java | 1613 +++--- .../jsyntaxpane/lexers/actionscript.flex | 194 +- 84 files changed, 11171 insertions(+), 11238 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PopItem.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PushItem.java diff --git a/lib/jsyntaxpane-0.9.5.jar b/lib/jsyntaxpane-0.9.5.jar index bc4a42add2bfde2d7117126a4c17c7fa10de8b88..1625e6b2e7989947d66a0f04c8f287b42349442e 100644 GIT binary patch delta 381526 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

+faG@y@Ot{cAu#@z&o>+|f+Hy2{Ph_PxvPt?X2< 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%0D*}r+lZHcvir|7H2M4|so;{L;9l@o} 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 sPUy#OP1k%w4JWC2p*PgVV@ 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 T$I9z>bdIZk3(j>+cPlCD1uh>r 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

2eCItP-b%t#5q@q!R_(43*xyWrxw3re?q}&b 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 diff --git a/libsrc/ffdec_lib/lexers/actionscript3_script.flex b/libsrc/ffdec_lib/lexers/actionscript3_script.flex index 8e393ed1f..f0b94ba62 100644 --- a/libsrc/ffdec_lib/lexers/actionscript3_script.flex +++ b/libsrc/ffdec_lib/lexers/actionscript3_script.flex @@ -1,16 +1,16 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ @@ -21,7 +21,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Stack; -%% +%% %public %class ActionScriptLexer @@ -37,7 +37,7 @@ import java.util.Stack; public ActionScriptLexer(String sourceCode){ this(new StringReader(sourceCode)); - this.sourceCode = sourceCode; + this.sourceCode = sourceCode; } public void yypushbackstr(String s, int state) @@ -115,7 +115,7 @@ InputCharacter = [^\r\n] WhiteSpace = {LineTerminator} | [ \t\f]+ /* comments */ -Comment = {TraditionalComment} | {EndOfLineComment} +Comment = {TraditionalComment} | {EndOfLineComment} TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/" EndOfLineComment = "//" {InputCharacter}* {LineTerminator}? @@ -188,19 +188,20 @@ HexDigit = [0-9a-fA-F] OctIntegerLiteral = 0+ [1-3]? {OctDigit} {1,15} OctDigit = [0-7] - -/* floating point literals */ + +/* floating point literals */ DoubleLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}? -FLit1 = [0-9]+ \. [0-9]* -FLit2 = \. [0-9]+ -FLit3 = [0-9]+ +FLit1 = [0-9]+ \. [0-9]* +FLit2 = \. [0-9]+ +FLit3 = [0-9]+ Exponent = [eE] [+-]? [0-9]+ /* string and character literals */ StringCharacter = [^\r\n\"\\] SingleCharacter = [^\r\n\'\\] OIdentifierCharacter = [^\r\n\u00A7\\] +Preprocessor = \u00A7\u00A7 {Identifier} %state STRING, CHARLITERAL,XMLOPENTAG,XMLOPENTAGATTRIB,XMLINSTROPENTAG,XMLINSTRATTRIB,XMLCDATA,XMLCOMMENT,XML,OIDENTIFIER @@ -252,7 +253,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] "false" { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); } "null" { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); } "this" { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); } - "true" { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); } + "true" { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); } "undefined" { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); } "Infinity" { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); } "NaN" { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); } @@ -261,99 +262,102 @@ OIdentifierCharacter = [^\r\n\u00A7\\] /* operators */ - "(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); } - ")" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); } - "{" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); } - "}" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); } - "[" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); } - "]" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); } - ";" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); } - "," { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); } - "..." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); } - "." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); } - "=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); } - ">" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); } - "<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); } - "!" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); } - "~" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); } - "?" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); } - ":" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); } - "===" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); } - "==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); } - "<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); } - ">=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); } - "!==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); } - "!=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); } - "&&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); } - "||" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); } - "++" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); } - "--" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); } - "+" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); } - "-" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); } - "*" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); } - "/" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); } - "&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); } - "|" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); } - "^" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); } - "%" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); } - "<<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); } - ">>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); } - ">>>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); } - "+=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); } - "-=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); } - "*=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); } - "/=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); } - "&=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); } - "|=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); } - "^=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); } - "%=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); } - "<<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); } - ">>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); } - ">>>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); } - "as" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); } - "delete" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); } - "instanceof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); } - "is" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); } - "::" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); } - "new" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); } - "typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); } - "void" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); } - "@" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); } + "(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); } + ")" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); } + "{" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); } + "}" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); } + "[" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); } + "]" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); } + ";" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); } + "," { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); } + "..." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); } + "." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); } + "=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); } + ">" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); } + "<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); } + "!" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); } + "~" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); } + "?" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); } + ":" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); } + "===" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); } + "==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); } + "<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); } + ">=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); } + "!==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); } + "!=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); } + "&&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); } + "||" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); } + "++" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); } + "--" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); } + "+" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); } + "-" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); } + "*" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); } + "/" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); } + "&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); } + "|" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); } + "^" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); } + "%" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); } + "<<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); } + ">>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); } + ">>>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); } + "+=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); } + "-=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); } + "*=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); } + "/=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); } + "&=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); } + "|=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); } + "^=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); } + "%=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); } + "<<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); } + ">>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); } + ">>>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); } + "as" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); } + "delete" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); } + "instanceof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); } + "is" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); } + "::" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); } + "new" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); } + "typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); } + "void" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); } + "@" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); } ".(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FILTER, yytext()); } ".." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DESCENDANTS, yytext()); } - + /* string literal */ - \" { + \" { string.setLength(0); - yybegin(STRING); + yybegin(STRING); } - "\u00A7" { + {Preprocessor} { + return new ParsedSymbol(SymbolGroup.PREPROCESSOR, SymbolType.PREPROCESSOR, yytext().substring(2)); + } + "\u00A7" { string.setLength(0); - yybegin(OIDENTIFIER); + yybegin(OIDENTIFIER); } /* character literal */ - \' { + \' { string.setLength(0); - yybegin(CHARLITERAL); + yybegin(CHARLITERAL); } /* numeric literals */ {DecIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); } - + {HexIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); } - + {OctIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); } - + {DoubleLiteral} { return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); } - + /* comments */ {Comment} { /*ignore*/ } {LineTerminator} { yyline++;} /* whitespace */ - {WhiteSpace} { /*ignore*/ } + {WhiteSpace} { /*ignore*/ } {TypeNameSpec} { return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, yytext()); } {XmlOpenTagStart} { yybegin(XMLOPENTAG); @@ -361,9 +365,9 @@ OIdentifierCharacter = [^\r\n\u00A7\\] return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext()); } "<{" { return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext()); } - /* identifiers */ - {Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); } - + /* identifiers */ + {Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); } + } { @@ -402,9 +406,9 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.setLength(0); } return lex(); - } + } {LineTerminator} { string.append(yytext()); yyline++;} - {WhiteSpace} { string.append(yytext()); } + {WhiteSpace} { string.append(yytext()); } } @@ -416,8 +420,8 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } "{" { yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRVALVAR_BEGIN, yytext()); - } + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRVALVAR_BEGIN, yytext()); + } } @@ -448,7 +452,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.setLength(0); } return lex(); - } + } {LineTerminator} { string.append(yytext()); yyline++;} {WhiteSpace} { string.append(yytext()); } } @@ -461,11 +465,11 @@ OIdentifierCharacter = [^\r\n\u00A7\\] \"{XmlSQuoteStringChar}*\" { yybegin(XMLINSTROPENTAG); return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); - } + } "{" { yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRVALVAR_BEGIN, yytext()); - } + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRVALVAR_BEGIN, yytext()); + } } @@ -529,14 +533,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } return lex(); } - {XmlCloseTag} { + {XmlCloseTag} { pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHTAG, yytext())); if (string.length() > 0){ pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); string.setLength(0); } return lex(); - } + } "<{" { yybegin(YYINITIAL); @@ -547,7 +551,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } return lex(); } - " 0){ @@ -555,8 +559,8 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.setLength(0); } return lex(); - } - "{" { + } + "{" { yybegin(YYINITIAL); pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_VAR_BEGIN, yytext())); if (string.length() > 0){ @@ -564,18 +568,18 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.setLength(0); } return lex(); - } + } {LineTerminator} { string.append(yytext()); yyline++;} [^] { string.append(yytext()); } } { - "\u00A7" { - yybegin(YYINITIAL); + "\u00A7" { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); } - + {OIdentifierCharacter}+ { string.append(yytext()); } /* escape sequences */ @@ -590,7 +594,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { throw new AVM2ParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); } @@ -598,12 +602,12 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \" { - yybegin(YYINITIAL); + \" { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); } - + {StringCharacter}+ { string.append(yytext()); } /* escape sequences */ @@ -619,7 +623,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { /* ignore illegal character escape */ } @@ -627,14 +631,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \' { - yybegin(YYINITIAL); + \' { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); } - + {SingleCharacter}+ { string.append(yytext()); } - + /* escape sequences */ "\\b" { string.append('\b'); } "\\t" { string.append('\t'); } @@ -648,7 +652,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { /* ignore illegal character escape */ } diff --git a/libsrc/ffdec_lib/lexers/actionscript_script.flex b/libsrc/ffdec_lib/lexers/actionscript_script.flex index 350dca603..d00294b43 100644 --- a/libsrc/ffdec_lib/lexers/actionscript_script.flex +++ b/libsrc/ffdec_lib/lexers/actionscript_script.flex @@ -1,16 +1,16 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ @@ -20,7 +20,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Stack; -%% +%% %public %class ActionScriptLexer @@ -95,7 +95,7 @@ InputCharacter = [^\r\n] WhiteSpace = {LineTerminator} | [ \t\f]+ /* comments */ -Comment = {TraditionalComment} | {EndOfLineComment} +Comment = {TraditionalComment} | {EndOfLineComment} TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/" EndOfLineComment = "//" {InputCharacter}* {LineTerminator}? @@ -123,13 +123,13 @@ HexDigit = [0-9a-fA-F] OctIntegerLiteral = 0+ [1-3]? {OctDigit} {1,15} OctDigit = [0-7] - -/* floating point literals */ + +/* floating point literals */ DoubleLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}? -FLit1 = [0-9]+ \. [0-9]* -FLit2 = \. [0-9]+ -FLit3 = [0-9]+ +FLit1 = [0-9]+ \. [0-9]* +FLit2 = \. [0-9]+ +FLit3 = [0-9]+ Exponent = [eE] [+-]? [0-9]+ /* string and character literals */ @@ -137,6 +137,8 @@ StringCharacter = [^\r\n\"\\] SingleCharacter = [^\r\n\'\\] OIdentifierCharacter = [^\r\n\u00A7\\] +Preprocessor = \u00A7\u00A7 {Identifier} + %state STRING, CHARLITERAL, XMLSTARTTAG, XML, OIDENTIFIER %% @@ -236,108 +238,112 @@ OIdentifierCharacter = [^\r\n\u00A7\\] "unloadMovie" { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIE, yytext()); } "unloadMovieNum" { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIENUM, yytext()); } "fscommand" { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.FSCOMMAND, yytext()); } - + /* operators */ - "(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); } - ")" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); } - "{" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); } - "}" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); } - "[" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); } - "]" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); } - ";" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); } - "," { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); } - "..." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); } - "." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); } - "=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); } - ">" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); } - "<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); } - "!" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); } - "~" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); } - "?" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); } - ":" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); } - "===" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); } - "==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); } - "<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); } - ">=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); } - "!==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); } - "!=" | "<>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); } - "&&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); } - "||" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); } - "++" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); } - "--" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); } - "+" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); } - "-" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); } - "*" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); } - "/" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); } - "&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); } - "|" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); } - "^" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); } - "%" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); } - "<<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); } - ">>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); } - ">>>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); } - "+=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); } - "-=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); } - "*=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); } - "/=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); } - "&=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); } - "|=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); } - "^=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); } - "%=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); } - "<<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); } - ">>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); } - ">>>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); } - "as" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); } - "delete" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); } - "instanceof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); } - "is" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); } - "::" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); } - "new" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); } - "typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); } - "void" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); } - "@" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); } - "and" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLAND, yytext()); } - "or" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLOR, yytext()); } - + "(" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); } + ")" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); } + "{" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); } + "}" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); } + "[" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); } + "]" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); } + ";" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); } + "," { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); } + "..." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); } + "." { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); } + "=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); } + ">" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); } + "<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); } + "!" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); } + "~" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); } + "?" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); } + ":" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); } + "===" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); } + "==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); } + "<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); } + ">=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); } + "!==" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); } + "!=" | "<>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); } + "&&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); } + "||" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); } + "++" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); } + "--" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); } + "+" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); } + "-" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); } + "*" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); } + "/" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); } + "&" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); } + "|" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); } + "^" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); } + "%" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); } + "<<" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); } + ">>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); } + ">>>" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); } + "+=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); } + "-=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); } + "*=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); } + "/=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); } + "&=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); } + "|=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); } + "^=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); } + "%=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); } + "<<=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); } + ">>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); } + ">>>=" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); } + "as" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); } + "delete" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); } + "instanceof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); } + "is" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); } + "::" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); } + "new" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); } + "typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); } + "void" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); } + "@" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); } + "and" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLAND, yytext()); } + "or" { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLOR, yytext()); } + /* string literal */ - \" { + \" { string.setLength(0); - yybegin(STRING); + yybegin(STRING); } - "\u00A7" { + {Preprocessor} { + return new ParsedSymbol(SymbolGroup.PREPROCESSOR, SymbolType.PREPROCESSOR, yytext().substring(2)); + } + + "\u00A7" { string.setLength(0); - yybegin(OIDENTIFIER); - } + yybegin(OIDENTIFIER); + } /* character literal */ - \' { + \' { string.setLength(0); - yybegin(CHARLITERAL); + yybegin(CHARLITERAL); } /* numeric literals */ {DecIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); } - + {HexIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); } - + {OctIntegerLiteral} { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); } - + {DoubleLiteral} { return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); } - + /* comments */ {Comment} { /*ignore*/ } {LineTerminator} { yyline++;} /* whitespace */ - {WhiteSpace} { /*ignore*/ } + {WhiteSpace} { /*ignore*/ } {TypeNameSpec} { String t = yytext(); return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, t.substring(2, t.length() - 1)); } {XMLBeginOneTag} {string.setLength(0); - yybegin(XML); - String s = yytext(); + yybegin(XML); + String s = yytext(); s = s.substring(1, s.length() - 1); if (s.contains(" ")){ s = s.substring(0, s.indexOf(' ')); @@ -345,8 +351,8 @@ OIdentifierCharacter = [^\r\n\u00A7\\] xmlTagName = s; string.append(yytext()); } - /* identifiers */ - {Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); } + /* identifiers */ + {Identifier} { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); } } { @@ -359,7 +365,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] {XMLBeginOneTag} { string.append(yytext());} {XMLEndTag} { string.append(yytext()); String endtagname = yytext(); - endtagname = endtagname.substring(2, endtagname.length() - 1); + endtagname = endtagname.substring(2, endtagname.length() - 1); if (endtagname.equals(xmlTagName)){ yybegin(YYINITIAL); return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML, string.toString()); @@ -370,12 +376,12 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - "\u00A7" { - yybegin(YYINITIAL); + "\u00A7" { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); } - + {OIdentifierCharacter}+ { string.append(yytext()); } /* escape sequences */ @@ -390,7 +396,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { throw new ActionParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); } @@ -398,12 +404,12 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \" { - yybegin(YYINITIAL); + \" { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); } - + {StringCharacter}+ { string.append(yytext()); } /* escape sequences */ @@ -414,14 +420,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] "\\r" { string.append('\r'); } "\\\"" { string.append('\"'); } "\\'" { string.append('\''); } - "\\\\" { string.append('\\'); } + "\\\\" { string.append('\\'); } \\x{HexDigit}{2} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } \\{OctDigit}{3} { char val = (char) Integer.parseInt(yytext().substring(1), 8); string.append(val); } - + /* escape sequences */ \\. { string.append('\\'); /*illegal escape sequence*/ } @@ -429,14 +435,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \' { - yybegin(YYINITIAL); + \' { + yybegin(YYINITIAL); // length also includes the trailing quote return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); } - + {SingleCharacter}+ { string.append(yytext()); } - + /* escape sequences */ /* escape sequences */ "\\b" { string.append('\b'); } @@ -451,7 +457,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] string.append(val); } \\u{HexDigit}{4} { char val = (char) Integer.parseInt(yytext().substring(2), 16); string.append(val); } - + /* escape sequences */ \\. { string.append('\\'); /*illegal escape sequence*/ } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 017984d3f..172d0602c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -1736,7 +1736,7 @@ public final class SWF implements SWFContainerItem, Timelined { private static void getVariables(List> variables, List functions, HashMap strings, HashMap usageTypes, ActionGraphSource code, int addr, String path) throws InterruptedException { ActionLocalData localData = new ActionLocalData(); - getVariables(null, localData, new TranslateStack(), new ArrayList(), code, code.adr2pos(addr), variables, functions, strings, new ArrayList(), usageTypes, path); + getVariables(null, localData, new TranslateStack(path), new ArrayList(), code, code.adr2pos(addr), variables, functions, strings, new ArrayList(), usageTypes, path); } private List> getVariables(List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes, ASMSource src, String path) throws InterruptedException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java index 212210862..c62dd113d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.graph.ScopeStack; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @@ -56,9 +57,10 @@ public class AVM2LocalData extends BaseLocalData { public ArrayList parsedExceptions; - public ArrayList finallyJumps; + public Map> finallyJumps; - public ArrayList ignoredSwitches; + public Map ignoredSwitches; + public List ignoredSwitches2; public Integer scriptIndex; @@ -88,6 +90,7 @@ public class AVM2LocalData extends BaseLocalData { parsedExceptions = localData.parsedExceptions; finallyJumps = localData.finallyJumps; ignoredSwitches = localData.ignoredSwitches; + ignoredSwitches2 = localData.ignoredSwitches2; scriptIndex = localData.scriptIndex; localRegAssignmentIps = localData.localRegAssignmentIps; ip = localData.ip; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 8653f2fb3..0e3c62f4c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -282,6 +282,7 @@ import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateException; import com.jpexs.decompiler.graph.TranslateStack; import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.model.ExitItem; import com.jpexs.decompiler.graph.model.ScriptEndItem; import com.jpexs.helpers.Helper; import java.io.ByteArrayInputStream; @@ -1243,8 +1244,8 @@ public class AVM2Code implements Cloneable { if (isKilled(((SetLocalAVM2Item) output.get(i)).regIndex, 0, code.size() - 1)) { SetLocalAVM2Item lsi = (SetLocalAVM2Item) output.get(i); if (i + 1 < output.size()) { - if (output.get(i + 1) instanceof ReturnValueAVM2Item) { - ReturnValueAVM2Item rv = (ReturnValueAVM2Item) output.get(i + 1); + if (output.get(i + 1) instanceof ExitItem) { + GraphTargetItem rv = output.get(i + 1); if (rv.value instanceof LocalRegAVM2Item) { LocalRegAVM2Item lr = (LocalRegAVM2Item) rv.value; if (lr.regIndex == lsi.regIndex) { @@ -1442,7 +1443,7 @@ public class AVM2Code implements Cloneable { } } if (!isKilled(reg, 0, end)) { - GraphTargetItem vx = stack.pop(); + GraphTargetItem vx = stack.pop().getThroughDuplicate(); int dupCnt = 1; for (int i = ip - 1; i >= start; i--) { if (code.get(i).definition instanceof DupIns) { @@ -1899,6 +1900,7 @@ public class AVM2Code implements Cloneable { ret.parsedExceptions = localData.parsedExceptions; ret.finallyJumps = localData.finallyJumps; ret.ignoredSwitches = localData.ignoredSwitches; + ret.ignoredSwitches2 = localData.ignoredSwitches2; ret.scriptIndex = localData.scriptIndex; ret.localRegAssignmentIps = localData.localRegAssignmentIps; ret.ip = localData.ip; @@ -1921,8 +1923,9 @@ public class AVM2Code implements Cloneable { localData.localRegNames = body.getLocalRegNames(abc); localData.fullyQualifiedNames = new ArrayList<>(); localData.parsedExceptions = new ArrayList<>(); - localData.finallyJumps = new ArrayList<>(); - localData.ignoredSwitches = new ArrayList<>(); + localData.finallyJumps = new HashMap<>(); + localData.ignoredSwitches = new HashMap<>(); + localData.ignoredSwitches2 = new ArrayList<>(); localData.scriptIndex = scriptIndex; localData.localRegAssignmentIps = new HashMap<>(); localData.ip = 0; @@ -2958,7 +2961,7 @@ public class AVM2Code implements Cloneable { public static int removeTraps(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, AVM2LocalData localData, AVM2GraphSource code, int addr, String path, HashMap> refs) throws InterruptedException { HashMap decisions = new HashMap<>(); - removeTraps(refs, false, false, localData, new TranslateStack(), new ArrayList(), code, code.adr2pos(addr), new HashMap(), new HashMap>(), decisions, path, 0); + removeTraps(refs, false, false, localData, new TranslateStack(path), new ArrayList(), code, code.adr2pos(addr), new HashMap(), new HashMap>(), decisions, path, 0); int cnt = 0; for (AVM2Instruction src : decisions.keySet()) { Decision dec = decisions.get(src); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 75beee2bf..c29e13c1c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.HasNextAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.InAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NextNameAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NextValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; @@ -69,6 +70,8 @@ import com.jpexs.decompiler.graph.model.ExitItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.LoopItem; import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.PushItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.WhileItem; import java.util.ArrayList; @@ -76,6 +79,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @@ -124,8 +128,9 @@ public class AVM2Graph extends Graph { localData.localRegNames = localRegNames; localData.fullyQualifiedNames = fullyQualifiedNames; localData.parsedExceptions = new ArrayList<>(); - localData.finallyJumps = new ArrayList<>(); - localData.ignoredSwitches = new ArrayList<>(); + localData.finallyJumps = new HashMap<>(); + localData.ignoredSwitches = new HashMap<>(); + localData.ignoredSwitches2 = new ArrayList<>(); localData.scriptIndex = scriptIndex; localData.localRegAssignmentIps = new HashMap<>(); localData.ip = 0; @@ -159,26 +164,6 @@ public class AVM2Graph extends Graph { } } } - - /*for(ABCException ex:body.exceptions){ - for(GraphPart p:allBlocks){ - boolean next_is_ex_start=false; - for(GraphPart n:p.nextParts){ - if(n.start==code.adr2pos(ex.start)){ - next_is_ex_start = true; - break; - } - } - if(next_is_ex_start){ - for(GraphPart q:allBlocks){ //find target part - if(q.start==code.adr2pos(ex.target)){ - p.nextParts.add(q); - break; - } - } - } - } - }*/ } @Override @@ -187,11 +172,13 @@ public class AVM2Graph extends Graph { AVM2LocalData aLocalData = (AVM2LocalData) localData; List parsedExceptions = aLocalData.parsedExceptions; - List finallyJumps = aLocalData.finallyJumps; - List ignoredSwitches = aLocalData.ignoredSwitches; + Map> finallyJumps = aLocalData.finallyJumps; + Map ignoredSwitches = aLocalData.ignoredSwitches; + List ignoredSwitches2 = aLocalData.ignoredSwitches2; int ip = part.start; int addr = this.avm2code.fixAddrAfterDebugLine(this.avm2code.pos2adr(part.start)); int maxend = -1; + List catchedFinallys = new ArrayList<>(); List catchedExceptions = new ArrayList<>(); for (int e = 0; e < body.exceptions.length; e++) { if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) { @@ -200,11 +187,13 @@ public class AVM2Graph extends Graph { if (!parsedExceptions.contains(body.exceptions[e])) { if (((body.exceptions[e].end) > maxend)) { catchedExceptions.clear(); + catchedFinallys.clear(); maxend = this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end); catchedExceptions.add(body.exceptions[e]); } else if (this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) == maxend) { catchedExceptions.add(body.exceptions[e]); } + catchedFinallys.add(e); } } else if (body.exceptions[e].isFinally()) { @@ -233,14 +222,16 @@ public class AVM2Graph extends Graph { List finallyCommands = new ArrayList<>(); boolean hasFinally = false; int returnPos = afterCatchPos; + int finStart = -1; for (int e = 0; e < body.exceptions.length; e++) { if (body.exceptions[e].isFinally()) { if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) { if (afterCatchPos + 1 == code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))) { + catchedFinallys.add(e); AVM2Instruction jmpIns = this.avm2code.code.get(code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))); if (jmpIns.definition instanceof JumpIns) { - int finStart = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]); + finStart = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]); GraphPart fpart = null; for (GraphPart p : allParts) { @@ -249,6 +240,8 @@ public class AVM2Graph extends Graph { break; } } + TranslateStack st = (TranslateStack) stack.clone(); + st.clear(); int swPos = -1; for (int f = finStart; f < this.avm2code.code.size(); f++) { if (this.avm2code.code.get(f).definition instanceof LookupSwitchIns) { @@ -256,7 +249,7 @@ public class AVM2Graph extends Graph { if (swins.operands.length >= 3) { if (swins.operands[0] == swins.getBytes().length) { if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) { - stack.push(new ExceptionAVM2Item(body.exceptions[e])); + //st.push(new ExceptionAVM2Item(body.exceptions[e])); GraphPart fepart = null; for (GraphPart p : allParts) { if (p.start == f + 1) { @@ -280,13 +273,17 @@ public class AVM2Graph extends Graph { } //ignoredSwitches.add(-1); //int igs_size=ignoredSwitches.size(); - List oldFinallyJumps = new ArrayList<>(finallyJumps); + Map> oldFinallyJumps = new HashMap<>(finallyJumps); finallyJumps.clear(); - ignoredSwitches.add(swPos); - finallyCommands = printGraph(localData, stack, allParts, parent, fpart, null, loops, staticOperation, path); + ignoredSwitches.put(e, swPos); + st.push(new PopItem(null)); + finallyCommands = printGraph(localData, st, allParts, parent, fpart, null, loops, staticOperation, path); //ignoredSwitches.remove(igs_size-1); - finallyJumps.addAll(oldFinallyJumps); - finallyJumps.add(finStart); + finallyJumps.putAll(oldFinallyJumps); + if (!finallyJumps.containsKey(e)) { + finallyJumps.put(e, new ArrayList<>()); + } + finallyJumps.get(e).add(finStart); hasFinally = true; break; } @@ -328,7 +325,9 @@ public class AVM2Graph extends Graph { break; } } - stack.add(new ExceptionAVM2Item(catchedExceptions.get(e))); + TranslateStack st2 = (TranslateStack) stack.clone(); + st2.clear(); + st2.add(new ExceptionAVM2Item(catchedExceptions.get(e))); AVM2LocalData localData2 = new AVM2LocalData(aLocalData); localData2.scopeStack = new ScopeStack(); List stopPart2 = new ArrayList<>(stopPart); @@ -336,16 +335,18 @@ public class AVM2Graph extends Graph { if (retPart != null) { stopPart2.add(retPart); } - List ncatchedCommands = printGraph(localData2, stack, allParts, parent, npart, stopPart2, loops, staticOperation, path); + + List ncatchedCommands = printGraph(localData2, st2, allParts, parent, npart, stopPart2, loops, staticOperation, path); if (catchedExceptions.get(e).isFinally() && (catchedExceptions.size() > 1 || hasFinally)) { catchedExceptions.remove(e); e--; } else { catchedCommands.add(ncatchedCommands); if (retPart != null && avm2code.code.get(retPart.start).isExit() && !(!ncatchedCommands.isEmpty() && (ncatchedCommands.get(ncatchedCommands.size() - 1) instanceof ExitItem))) { - avm2code.code.get(retPart.start).translate(localData, stack, ncatchedCommands, staticOperation, path); + avm2code.code.get(retPart.start).translate(localData, st2, ncatchedCommands, staticOperation, path); } if (catchedExceptions.get(e).isFinally()) { + //endposStartBlock = -1; if (!ncatchedCommands.isEmpty() && (ncatchedCommands.get(0) instanceof SetLocalAVM2Item)) { SetLocalAVM2Item sl = (SetLocalAVM2Item) ncatchedCommands.get(0); if (sl.value.getNotCoerced() instanceof ExceptionAVM2Item) { @@ -364,19 +365,31 @@ public class AVM2Graph extends Graph { break; } } - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(nepart); + List stopPart2 = new ArrayList<>();//stopPart); + if (nepart != null) { + stopPart2.add(nepart); + } stopPart2.addAll(catchParts); if (retPart != null) { stopPart2.add(retPart); } - List tryCommands = printGraph(localData, stack, allParts, parent, part, stopPart2, loops, staticOperation, path); + TranslateStack st = (TranslateStack) stack.clone(); + st.clear(); + List tryCommands = printGraph(localData, st, allParts, parent, part, stopPart2, loops, staticOperation, path); if (retPart != null && avm2code.code.get(retPart.start).isExit() && !(!tryCommands.isEmpty() && (tryCommands.get(tryCommands.size() - 1) instanceof ExitItem))) { - avm2code.code.get(retPart.start).translate(localData, stack, tryCommands, staticOperation, path); + avm2code.code.get(retPart.start).translate(localData, st, tryCommands, staticOperation, path); } output.clear(); + stack.clear(); output.add(new TryAVM2Item(tryCommands, catchedExceptions, catchedCommands, finallyCommands, finCatchName)); + finallyJumps = ((AVM2LocalData) localData).finallyJumps; + for (int fin_e : catchedFinallys) { + if (finallyJumps.containsKey(fin_e)) { + finallyJumps.get(fin_e).clear(); + } + //.remove((Integer) finStart); + } ip = returnPos; } @@ -397,7 +410,10 @@ public class AVM2Graph extends Graph { ret.addAll(output); GraphTargetItem lop = checkLoop(part, stopPart, loops); if (lop == null) { - ret.addAll(printGraph(localData, stack, allParts, null, part, stopPart, loops, staticOperation, path)); + TranslateStack st = (TranslateStack) stack.clone(); + st.clear(); + + ret.addAll(printGraph(localData, st, allParts, null, part, stopPart, loops, staticOperation, path)); } else { ret.add(lop); } @@ -423,7 +439,7 @@ public class AVM2Graph extends Graph { } } } - if ((this.avm2code.code.get(part.end).definition instanceof LookupSwitchIns) && ignoredSwitches.contains(part.end)) { + if ((this.avm2code.code.get(part.end).definition instanceof LookupSwitchIns) && (ignoredSwitches.containsValue(part.end) || ignoredSwitches2.contains(part.end))) { ret = new ArrayList<>(); ret.addAll(output); return ret; @@ -444,9 +460,9 @@ public class AVM2Graph extends Graph { && (this.avm2code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns))) { if (stack.peek() instanceof StrictEqAVM2Item) { - ignoredSwitches.add(part.nextParts.get(0).nextParts.get(0).end); + ignoredSwitches2.add(part.nextParts.get(0).nextParts.get(0).end); } else { - ignoredSwitches.add(part.nextParts.get(1).nextParts.get(0).end); + ignoredSwitches2.add(part.nextParts.get(1).nextParts.get(0).end); } ret = new ArrayList<>(); ret.addAll(output); @@ -494,7 +510,7 @@ public class AVM2Graph extends Graph { } GraphPart numPart = part.nextParts.get(reversed ? 0 : 1); AVM2Instruction ins = null; - TranslateStack sstack = new TranslateStack(); + TranslateStack sstack = new TranslateStack(path); do { for (int n = 0; n < numPart.getHeight(); n++) { ins = this.avm2code.code.get(numPart.getPosAt(n)); @@ -535,7 +551,7 @@ public class AVM2Graph extends Graph { GraphPart numPart = dp; AVM2Instruction ins = null; - TranslateStack sstack = new TranslateStack(); + TranslateStack sstack = new TranslateStack(path); do { for (int n = 0; n < numPart.getHeight(); n++) { ins = this.avm2code.code.get(numPart.getPosAt(n)); @@ -636,33 +652,34 @@ public class AVM2Graph extends Graph { @Override protected GraphPart checkPart(TranslateStack stack, BaseLocalData localData, GraphPart next, List allParts) { AVM2LocalData aLocalData = (AVM2LocalData) localData; - List finallyJumps = aLocalData.finallyJumps; - List ignoredSwitches = aLocalData.ignoredSwitches; + Map> finallyJumps = aLocalData.finallyJumps; + Map ignoredSwitches = aLocalData.ignoredSwitches; GraphPart ret = next; - for (int f = 0; f < finallyJumps.size(); f++) { - int fip = finallyJumps.get(f); + for (int f : finallyJumps.keySet()) {//int f = 0; f < finallyJumps.size(); f++) { int swip = ignoredSwitches.get(f); - if (next.start == fip) { - if (stack != null && swip != -1) { - AVM2Instruction swIns = avm2code.code.get(swip); - GraphTargetItem t = stack.pop(); - Double dval = EcmaScript.toNumber(t.getResult()); - int val = (int) (double) dval; - if (swIns.definition instanceof LookupSwitchIns) { - List branches = swIns.getBranches(code); - int nip = branches.get(0); - if (val >= 0 && val < branches.size() - 1) { - nip = branches.get(1 + val); - } - for (GraphPart p : allParts) { - if (avm2code.fixIPAfterDebugLine(p.start) == avm2code.fixIPAfterDebugLine(nip)) { - return p; + for (int fip : finallyJumps.get(f)) { + if (next.start == fip) { + if (stack != null && swip != -1) { + AVM2Instruction swIns = avm2code.code.get(swip); + GraphTargetItem t = stack.pop(); + Double dval = EcmaScript.toNumber(t.getResult()); + int val = (int) (double) dval; + if (swIns.definition instanceof LookupSwitchIns) { + List branches = swIns.getBranches(code); + int nip = branches.get(0); + if (val >= 0 && val < branches.size() - 1) { + nip = branches.get(1 + val); } + for (GraphPart p : allParts) { + if (avm2code.fixIPAfterDebugLine(p.start) == avm2code.fixIPAfterDebugLine(nip)) { + return p; + } + } + ret = null; } - ret = null; } + ret = null; } - ret = null; } } if (ret != next) { @@ -678,8 +695,14 @@ public class AVM2Graph extends Graph { AVM2Instruction jmpIns = this.avm2code.code.get(avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))); if (jmpIns.definition instanceof JumpIns) { int finStart = avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]); - finallyJumps.add(finStart); - ignoredSwitches.add(-1); + if (!finallyJumps.containsKey(e)) { + finallyJumps.put(e, new ArrayList<>()); + } + finallyJumps.get(e).add(finStart); + if (!ignoredSwitches.containsKey(e)) { + ignoredSwitches.put(e, -1); + } + //ignoredSwitches.put(e, -1); break; } } @@ -707,7 +730,11 @@ public class AVM2Graph extends Graph { } GraphTargetItem ft = w.commands.get(pos); if (ft instanceof WithAVM2Item) { - ft = w.commands.get(pos + 1); + pos++; + while (w.commands.get(pos) instanceof SetTypeAVM2Item) { + pos++; + } + ft = w.commands.get(pos); if (ft instanceof IfItem) { IfItem ift = (IfItem) ft; if (ift.onTrue.size() > 0) { @@ -759,7 +786,7 @@ public class AVM2Graph extends Graph { @Override protected void finalProcess(List list, int level, FinalProcessLocalData localData) { - super.finalProcess(list, level, localData); + if (level == 0) { if (!list.isEmpty()) { if (list.get(list.size() - 1) instanceof ReturnVoidAVM2Item) { @@ -864,6 +891,8 @@ public class AVM2Graph extends Graph { } } } + //Handle for loops at the end: + super.finalProcess(list, level, localData); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/NotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/NotIns.java index f222a3d22..121344f18 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/NotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/NotIns.java @@ -1,49 +1,49 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.NotItem; -import java.util.HashMap; -import java.util.List; - -public class NotIns extends InstructionDefinition { - - public NotIns() { - super(0x96, "not", new int[]{}, false); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem v = stack.pop(); - stack.push(new NotItem(ins, v)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1 + 1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.NotItem; +import java.util.HashMap; +import java.util.List; + +public class NotIns extends InstructionDefinition { + + public NotIns() { + super(0x96, "not", new int[]{}, false); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem v = stack.pop(); + stack.push(v.invert(ins)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1 + 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfFalseIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfFalseIns.java index 1ac54af7a..e71bdb9e8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfFalseIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfFalseIns.java @@ -1,56 +1,57 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.NotItem; -import java.util.HashMap; -import java.util.List; - -public class IfFalseIns extends InstructionDefinition implements IfTypeIns { - - public IfFalseIns() { - super(0x12, "iffalse", new int[]{AVM2Code.DAT_OFFSET}, false); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem v1 = stack.pop(); - stack.push(new NotItem(ins, v1)); - } - - @Override - public void translateInverted(HashMap localRegs, TranslateStack stack, AVM2Instruction ins) { - //String v1 = stack.pop().toString(); - //stack.push("(" + v1 + ")"); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.NotItem; +import java.util.HashMap; +import java.util.List; + +public class IfFalseIns extends InstructionDefinition implements IfTypeIns { + + public IfFalseIns() { + super(0x12, "iffalse", new int[]{AVM2Code.DAT_OFFSET}, false); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem v1 = stack.pop(); + //stack.push(new NotItem(ins, v1)); + stack.push(v1.invert(ins)); + } + + @Override + public void translateInverted(HashMap localRegs, TranslateStack stack, AVM2Instruction ins) { + //String v1 = stack.pop().toString(); + //stack.push("(" + v1 + ")"); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfTrueIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfTrueIns.java index 8f61976f0..dd59e4687 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfTrueIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/IfTrueIns.java @@ -1,56 +1,56 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.NotItem; -import java.util.HashMap; -import java.util.List; - -public class IfTrueIns extends InstructionDefinition implements IfTypeIns { - - public IfTrueIns() { - super(0x11, "iftrue", new int[]{AVM2Code.DAT_OFFSET}, false); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - //String v1 = stack.pop().toString(); - //stack.push("(" + v1 + ")"); - } - - @Override - public void translateInverted(HashMap localRegs, TranslateStack stack, AVM2Instruction ins) { - GraphTargetItem v1 = stack.pop(); - stack.push(new NotItem(ins, v1)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.NotItem; +import java.util.HashMap; +import java.util.List; + +public class IfTrueIns extends InstructionDefinition implements IfTypeIns { + + public IfTrueIns() { + super(0x11, "iftrue", new int[]{AVM2Code.DAT_OFFSET}, false); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + //String v1 = stack.pop().toString(); + //stack.push("(" + v1 + ")"); + } + + @Override + public void translateInverted(HashMap localRegs, TranslateStack stack, AVM2Instruction ins) { + GraphTargetItem v1 = stack.pop(); + stack.push(v1.invert(null)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java index 973dcde54..85895b8e5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java @@ -1,134 +1,134 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.instructions.SetTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.DecrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.PostDecrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.PostIncrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreDecrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; -import java.util.Stack; - -public abstract class SetLocalTypeIns extends InstructionDefinition implements SetTypeIns { - - public SetLocalTypeIns(int instructionCode, String instructionName, int[] operands, boolean canThrow) { - super(instructionCode, instructionName, operands, canThrow); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap regAssignCount, int ip, HashMap> refs, AVM2Code code) { - int regId = getRegisterId(ins); - GraphTargetItem value = stack.pop(); - /*if (localRegs.containsKey(regId)) { - localRegs.put(regId, new NotCompileTimeAVM2Item(ins, value)); - } else { - localRegs.put(regId, value); - }*/ - localRegs.put(regId, value); - if (!regAssignCount.containsKey(regId)) { - regAssignCount.put(regId, 0); - } - regAssignCount.put(regId, regAssignCount.get(regId) + 1); - //localRegsAssignmentIps.put(regId, ip); - if (value instanceof NewActivationAVM2Item) { - return; - } - if (value instanceof FindPropertyAVM2Item) { - return; - } - if (value.getNotCoerced() instanceof IncrementAVM2Item) { - GraphTargetItem inside = ((IncrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate(); - if (inside instanceof LocalRegAVM2Item) { - if (((LocalRegAVM2Item) inside).regIndex == regId) { - if (stack.size() > 0) { - GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); - if (top == inside) { - stack.pop(); - stack.push(new PostIncrementAVM2Item(ins, inside)); - } else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).value == inside)) { - stack.pop(); - stack.push(new PreIncrementAVM2Item(ins, inside)); - } else { - output.add(new PostIncrementAVM2Item(ins, inside)); - } - } else { - output.add(new PostIncrementAVM2Item(ins, inside)); - } - return; - } - } - } - - if (value.getNotCoerced() instanceof DecrementAVM2Item) { - GraphTargetItem inside = ((DecrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate(); - if (inside instanceof LocalRegAVM2Item) { - if (((LocalRegAVM2Item) inside).regIndex == regId) { - if (stack.size() > 0) { - GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); - if (top == inside) { - stack.pop(); - stack.push(new PostDecrementAVM2Item(ins, inside)); - } else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).value == inside)) { - stack.pop(); - stack.push(new PreDecrementAVM2Item(ins, inside)); - } else { - output.add(new PostDecrementAVM2Item(ins, inside)); - } - } else { - output.add(new PostDecrementAVM2Item(ins, inside)); - } - return; - } - } - } - - //if(val.startsWith("catchscope ")) return; - //if(val.startsWith("newactivation()")) return; - output.add(new SetLocalAVM2Item(ins, regId, value)); - } - - @Override - public String getObject(Stack stack, ABC abc, AVM2Instruction ins, List output, MethodBody body, HashMap localRegNames, List fullyQualifiedNames) { - return AVM2Item.localRegName(localRegNames, getRegisterId(ins)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1; - } - - public abstract int getRegisterId(AVM2Instruction ins); -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.SetTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.DecrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.PostDecrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.PostIncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreDecrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; +import java.util.Stack; + +public abstract class SetLocalTypeIns extends InstructionDefinition implements SetTypeIns { + + public SetLocalTypeIns(int instructionCode, String instructionName, int[] operands, boolean canThrow) { + super(instructionCode, instructionName, operands, canThrow); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap regAssignCount, int ip, HashMap> refs, AVM2Code code) { + int regId = getRegisterId(ins); + GraphTargetItem value = stack.pop(); + /*if (localRegs.containsKey(regId)) { + localRegs.put(regId, new NotCompileTimeAVM2Item(ins, value)); + } else { + localRegs.put(regId, value); + }*/ + localRegs.put(regId, value); + if (!regAssignCount.containsKey(regId)) { + regAssignCount.put(regId, 0); + } + regAssignCount.put(regId, regAssignCount.get(regId) + 1); + //localRegsAssignmentIps.put(regId, ip); + if (value.getThroughDuplicate() instanceof NewActivationAVM2Item) { + return; + } + if (value instanceof FindPropertyAVM2Item) { + return; + } + if (value.getNotCoerced() instanceof IncrementAVM2Item) { + GraphTargetItem inside = ((IncrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate(); + if (inside instanceof LocalRegAVM2Item) { + if (((LocalRegAVM2Item) inside).regIndex == regId) { + if (stack.size() > 0) { + GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); + if (top == inside) { + stack.pop(); + stack.push(new PostIncrementAVM2Item(ins, inside)); + } else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).value == inside)) { + stack.pop(); + stack.push(new PreIncrementAVM2Item(ins, inside)); + } else { + output.add(new PostIncrementAVM2Item(ins, inside)); + } + } else { + output.add(new PostIncrementAVM2Item(ins, inside)); + } + return; + } + } + } + + if (value.getNotCoerced() instanceof DecrementAVM2Item) { + GraphTargetItem inside = ((DecrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate(); + if (inside instanceof LocalRegAVM2Item) { + if (((LocalRegAVM2Item) inside).regIndex == regId) { + if (stack.size() > 0) { + GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); + if (top == inside) { + stack.pop(); + stack.push(new PostDecrementAVM2Item(ins, inside)); + } else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).value == inside)) { + stack.pop(); + stack.push(new PreDecrementAVM2Item(ins, inside)); + } else { + output.add(new PostDecrementAVM2Item(ins, inside)); + } + } else { + output.add(new PostDecrementAVM2Item(ins, inside)); + } + return; + } + } + } + + //if(val.startsWith("catchscope ")) return; + //if(val.startsWith("newactivation()")) return; + output.add(new SetLocalAVM2Item(ins, regId, value)); + } + + @Override + public String getObject(Stack stack, ABC abc, AVM2Instruction ins, List output, MethodBody body, HashMap localRegNames, List fullyQualifiedNames) { + return AVM2Item.localRegName(localRegNames, getRegisterId(ins)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1; + } + + public abstract int getRegisterId(AVM2Instruction ins); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java index aceb9e46e..7456f9eea 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java @@ -156,9 +156,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { } } } - if (slotname == null) { - System.err.println("SLOT NOT FOUND"); - } + output.add(new SetSlotAVM2Item(ins, obj, slotname, value)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java index 4865b4ff0..9abebbaaf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java @@ -45,13 +45,9 @@ public class PopIns extends InstructionDefinition { @Override public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - if (stack.size() > 0) { - GraphTargetItem top = stack.pop(); - //Note: Commands like "5;" - numbers are unsupported as it collide with try..finally block decompilation. TODO: allow this somehow - - if (/*!(top instanceof IntegerValueAVM2Item) &&*/(!(top instanceof MarkItem))) { - output.add(top); - } + GraphTargetItem top = stack.pop(); + if ((!(top instanceof MarkItem))) { + output.add(top); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushFalseIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushFalseIns.java index 8c32f6243..76076797c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushFalseIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushFalseIns.java @@ -1,54 +1,55 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class PushFalseIns extends InstructionDefinition { - - public PushFalseIns() { - super(0x27, "pushfalse", new int[]{}, false); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - lda.operandStack.push(Boolean.FALSE); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - stack.push(new BooleanAVM2Item(ins, Boolean.FALSE)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.FalseItem; +import java.util.HashMap; +import java.util.List; + +public class PushFalseIns extends InstructionDefinition { + + public PushFalseIns() { + super(0x27, "pushfalse", new int[]{}, false); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + lda.operandStack.push(Boolean.FALSE); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + stack.push(new FalseItem(ins)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushTrueIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushTrueIns.java index dc86afa3f..f87e6bb8d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushTrueIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushTrueIns.java @@ -1,54 +1,55 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class PushTrueIns extends InstructionDefinition { - - public PushTrueIns() { - super(0x26, "pushtrue", new int[]{}, false); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - lda.operandStack.push(Boolean.TRUE); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - stack.push(new BooleanAVM2Item(ins, Boolean.TRUE)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.TrueItem; +import java.util.HashMap; +import java.util.List; + +public class PushTrueIns extends InstructionDefinition { + + public PushTrueIns() { + super(0x26, "pushtrue", new int[]{}, false); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + lda.operandStack.push(Boolean.TRUE); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + stack.push(new TrueItem(ins)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/HasNextAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/HasNextAVM2Item.java index 671975b7f..12e3ca6a2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/HasNextAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/HasNextAVM2Item.java @@ -40,9 +40,9 @@ public class HasNextAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - collection.toString(writer, localData); + collection.appendTo(writer, localData); writer.append(" hasNext "); - return object.toString(writer, localData); + return object.appendTo(writer, localData); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java index dbe0fc1de..ce7c35d1a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -25,6 +26,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -78,4 +80,5 @@ public class IntegerValueAVM2Item extends NumberValueAVM2Item { public boolean hasReturnValue() { return true; } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewActivationAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewActivationAVM2Item.java index b664e18ef..a182b93e9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewActivationAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewActivationAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; @@ -32,7 +33,7 @@ public class NewActivationAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) { - return writer.append("newactivation()"); + return writer.append("§§activation"); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NumberValueAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NumberValueAVM2Item.java index 40f114929..3375c588e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NumberValueAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NumberValueAVM2Item.java @@ -1,25 +1,32 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.graph.SimpleValue; -public abstract class NumberValueAVM2Item extends AVM2Item { +public abstract class NumberValueAVM2Item extends AVM2Item implements SimpleValue { public NumberValueAVM2Item(AVM2Instruction instruction) { super(instruction, PRECEDENCE_PRIMARY); } + + @Override + public boolean isSimpleValue() { + return true; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSlotAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSlotAVM2Item.java index 989735dc2..68256562d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSlotAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSlotAVM2Item.java @@ -46,14 +46,14 @@ public class SetSlotAVM2Item extends AVM2Item implements SetTypeAVM2Item, Assign @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - srcData.localName = slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false); + srcData.localName = slotName == null ? "/*UnknownSlot*/" : slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false); getName(writer, localData); writer.append(" = "); return value.toString(writer, localData); } public String getNameAsStr(LocalData localData) { - return slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false); + return slotName == null ? "/*UnknownSlot*/" : slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false); } public GraphTextWriter getName(GraphTextWriter writer, LocalData localData) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/StringAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/StringAVM2Item.java index c99741759..b2d84022a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/StringAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/StringAVM2Item.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -31,7 +32,7 @@ import com.jpexs.helpers.Helper; import java.util.List; import java.util.Set; -public class StringAVM2Item extends AVM2Item { +public class StringAVM2Item extends AVM2Item implements SimpleValue { public String value; @@ -71,4 +72,9 @@ public class StringAVM2Item extends AVM2Item { public boolean hasReturnValue() { return true; } + + @Override + public boolean isSimpleValue() { + return true; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/EqAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/EqAVM2Item.java index fae5ce3b2..fe2f677bd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/EqAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/EqAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -53,7 +54,7 @@ public class EqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new NeqAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GeAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GeAVM2Item.java index aaf861327..2fa46b963 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GeAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GeAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class GeAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new LtAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GtAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GtAVM2Item.java index 32ec2e1d1..bacf5fffa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GtAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/GtAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class GtAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new LeAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LeAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LeAVM2Item.java index a65e4250a..017f5e700 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LeAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LeAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class LeAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new GtAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LtAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LtAVM2Item.java index bbfc82018..006d7b386 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LtAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/LtAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class LtAVM2Item extends BinaryOpItem implements LogicalOpItem, IfConditi } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new GeAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NeqAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NeqAVM2Item.java index 8e920d6df..69fc52490 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NeqAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NeqAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -54,7 +55,7 @@ public class NeqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfCondit } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new EqAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictEqAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictEqAVM2Item.java index e61d1196e..e13bce5a9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictEqAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictEqAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -56,7 +57,7 @@ public class StrictEqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfC } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new StrictNeqAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictNeqAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictNeqAVM2Item.java index cea963789..82cdae968 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictNeqAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/StrictNeqAVM2Item.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -49,7 +50,7 @@ public class StrictNeqAVM2Item extends BinaryOpItem implements LogicalOpItem, If } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new StrictEqAVM2Item(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index cd0302c22..13a7d5188 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -57,9 +57,11 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushWithIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; @@ -103,7 +105,6 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; 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.action.model.DirectValueActionItem; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; @@ -118,6 +119,7 @@ import com.jpexs.decompiler.graph.model.CommaExpressionItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.DoWhileItem; import com.jpexs.decompiler.graph.model.DuplicateItem; +import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.ForItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -125,6 +127,7 @@ import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; +import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; import com.jpexs.decompiler.graph.model.WhileItem; import java.io.ByteArrayOutputStream; @@ -161,6 +164,16 @@ public class AVM2SourceGenerator implements SourceGenerator { return new AVM2Instruction(0, def, operands); } + @Override + public List generate(SourceGeneratorLocalData localData, FalseItem item) throws CompilationException { + return GraphTargetItem.toSourceMerge(localData, this, ins(new PushFalseIns())); + } + + @Override + public List generate(SourceGeneratorLocalData localData, TrueItem item) throws CompilationException { + return GraphTargetItem.toSourceMerge(localData, this, ins(new PushTrueIns())); + } + public List generate(SourceGeneratorLocalData localData, GetDescendantsAVM2Item item) throws CompilationException { int[] nssa = new int[item.openedNamespaces.size()]; for (int i = 0; i < item.openedNamespaces.size(); i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java index d3d5d869f..1156095b9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java @@ -1,2344 +1,2128 @@ -/* The following code was generated by JFlex 1.6.0 */ - -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.parser.script; - -import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; -import java.util.Stack; - -/** - * This class is a scanner generated by - * JFlex 1.6.0 - * from the specification file - * C:/Projects/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/actionscript3_script.flex - */ -public final class ActionScriptLexer { - - /** - * This character denotes the end of file - */ - public static final int YYEOF = -1; - - /** - * initial size of the lookahead buffer - */ - private static final int ZZ_BUFFERSIZE = 16384; - - /** - * lexical states - */ - public static final int YYINITIAL = 0; - - public static final int STRING = 2; - - public static final int CHARLITERAL = 4; - - public static final int XMLOPENTAG = 6; - - public static final int XMLOPENTAGATTRIB = 8; - - public static final int XMLINSTROPENTAG = 10; - - public static final int XMLINSTRATTRIB = 12; - - public static final int XMLCDATA = 14; - - public static final int XMLCOMMENT = 16; - - public static final int XML = 18; - - public static final int OIDENTIFIER = 20; - - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l - * at the beginning of a line - * l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, - 8, 8, 9, 9, 10, 10 - }; - - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED - = "\11\0\1\13\1\2\1\113\1\3\1\1\22\0\1\13\1\14\1\33" - + "\1\0\1\6\1\110\1\105\1\34\1\76\1\77\1\5\1\45\1\103" - + "\1\15\1\11\1\4\1\35\3\41\4\42\2\21\1\17\1\102\1\12" - + "\1\32\1\16\1\23\1\111\1\27\1\20\1\25\1\26\1\43\1\20" - + "\2\10\1\74\4\10\1\75\5\10\1\30\3\10\1\37\2\10\1\24" - + "\1\46\1\31\1\107\1\10\1\0\1\52\1\50\1\54\1\63\1\44" - + "\1\40\1\73\1\66\1\61\1\10\1\53\1\64\1\71\1\57\1\56" - + "\1\67\1\10\1\51\1\55\1\60\1\62\1\72\1\65\1\36\1\70" - + "\1\10\1\100\1\106\1\101\1\104\6\0\1\113\41\0\1\47\2\0" - + "\1\6\12\0\1\6\1\0\1\22\2\0\1\6\5\0\2\6\1\112" - + "\24\6\1\0\37\6\1\0\u01ca\6\4\0\14\6\16\0\5\6\7\0" - + "\1\6\1\0\1\6\21\0\160\7\5\6\1\0\2\6\2\0\4\6" - + "\1\0\1\6\6\0\1\6\1\0\3\6\1\0\1\6\1\0\24\6" - + "\1\0\123\6\1\0\213\6\1\0\5\7\2\0\246\6\1\0\46\6" - + "\2\0\1\6\7\0\47\6\11\0\55\7\1\0\1\7\1\0\2\7" - + "\1\0\2\7\1\0\1\7\10\0\33\6\5\0\3\6\35\0\13\7" - + "\5\0\53\6\37\7\4\0\2\6\1\7\143\6\1\0\1\6\7\7" - + "\2\0\6\7\2\6\2\7\1\0\4\7\2\6\12\7\3\6\2\0" - + "\1\6\20\0\1\6\1\7\36\6\33\7\2\0\131\6\13\7\1\6" - + "\16\0\12\7\41\6\11\7\2\6\4\0\1\6\5\0\26\6\4\7" - + "\1\6\11\7\1\6\3\7\1\6\5\7\22\0\31\6\3\7\104\0" - + "\23\6\61\0\40\7\66\6\3\7\1\6\22\7\1\6\7\7\12\6" - + "\2\7\2\0\12\7\1\0\20\6\3\7\1\0\10\6\2\0\2\6" - + "\2\0\26\6\1\0\7\6\1\0\1\6\3\0\4\6\2\0\1\7" - + "\1\6\7\7\2\0\2\7\2\0\3\7\1\6\10\0\1\7\4\0" - + "\2\6\1\0\3\6\2\7\2\0\12\7\2\6\17\0\3\7\1\0" - + "\6\6\4\0\2\6\2\0\26\6\1\0\7\6\1\0\2\6\1\0" - + "\2\6\1\0\2\6\2\0\1\7\1\0\5\7\4\0\2\7\2\0" - + "\3\7\3\0\1\7\7\0\4\6\1\0\1\6\7\0\14\7\3\6" - + "\1\7\13\0\3\7\1\0\11\6\1\0\3\6\1\0\26\6\1\0" - + "\7\6\1\0\2\6\1\0\5\6\2\0\1\7\1\6\10\7\1\0" - + "\3\7\1\0\3\7\2\0\1\6\17\0\2\6\2\7\2\0\12\7" - + "\21\0\3\7\1\0\10\6\2\0\2\6\2\0\26\6\1\0\7\6" - + "\1\0\2\6\1\0\5\6\2\0\1\7\1\6\7\7\2\0\2\7" - + "\2\0\3\7\10\0\2\7\4\0\2\6\1\0\3\6\2\7\2\0" - + "\12\7\1\0\1\6\20\0\1\7\1\6\1\0\6\6\3\0\3\6" - + "\1\0\4\6\3\0\2\6\1\0\1\6\1\0\2\6\3\0\2\6" - + "\3\0\3\6\3\0\14\6\4\0\5\7\3\0\3\7\1\0\4\7" - + "\2\0\1\6\6\0\1\7\16\0\12\7\20\0\4\7\1\0\10\6" - + "\1\0\3\6\1\0\27\6\1\0\20\6\3\0\1\6\7\7\1\0" - + "\3\7\1\0\4\7\7\0\2\7\1\0\2\6\6\0\2\6\2\7" - + "\2\0\12\7\21\0\3\7\1\0\10\6\1\0\3\6\1\0\27\6" - + "\1\0\12\6\1\0\5\6\2\0\1\7\1\6\7\7\1\0\3\7" - + "\1\0\4\7\7\0\2\7\7\0\1\6\1\0\2\6\2\7\2\0" - + "\12\7\1\0\2\6\16\0\3\7\1\0\10\6\1\0\3\6\1\0" - + "\51\6\2\0\1\6\7\7\1\0\3\7\1\0\4\7\1\6\10\0" - + "\1\7\10\0\2\6\2\7\2\0\12\7\12\0\6\6\2\0\2\7" - + "\1\0\22\6\3\0\30\6\1\0\11\6\1\0\1\6\2\0\7\6" - + "\3\0\1\7\4\0\6\7\1\0\1\7\1\0\10\7\6\0\12\7" - + "\2\0\2\7\15\0\60\6\1\7\2\6\7\7\5\0\7\6\10\7" - + "\1\0\12\7\47\0\2\6\1\0\1\6\2\0\2\6\1\0\1\6" - + "\2\0\1\6\6\0\4\6\1\0\7\6\1\0\3\6\1\0\1\6" - + "\1\0\1\6\2\0\2\6\1\0\4\6\1\7\2\6\6\7\1\0" - + "\2\7\1\6\2\0\5\6\1\0\1\6\1\0\6\7\2\0\12\7" - + "\2\0\4\6\40\0\1\6\27\0\2\7\6\0\12\7\13\0\1\7" - + "\1\0\1\7\1\0\1\7\4\0\2\7\10\6\1\0\44\6\4\0" - + "\24\7\1\0\2\7\5\6\13\7\1\0\44\7\11\0\1\7\71\0" - + "\53\6\24\7\1\6\12\7\6\0\6\6\4\7\4\6\3\7\1\6" - + "\3\7\2\6\7\7\3\6\4\7\15\6\14\7\1\6\17\7\2\0" - + "\46\6\1\0\1\6\5\0\1\6\2\0\53\6\1\0\u014d\6\1\0" - + "\4\6\2\0\7\6\1\0\1\6\1\0\4\6\2\0\51\6\1\0" - + "\4\6\2\0\41\6\1\0\4\6\2\0\7\6\1\0\1\6\1\0" - + "\4\6\2\0\17\6\1\0\71\6\1\0\4\6\2\0\103\6\2\0" - + "\3\7\40\0\20\6\20\0\125\6\14\0\u026c\6\2\0\21\6\1\0" - + "\32\6\5\0\113\6\3\0\3\7\10\6\7\0\15\6\1\0\4\6" - + "\3\7\13\0\22\6\3\7\13\0\22\6\2\7\14\0\15\6\1\0" - + "\3\6\1\0\2\7\14\0\64\6\40\7\3\0\1\6\4\0\1\6" - + "\1\7\2\0\12\7\41\0\3\7\2\0\12\7\6\0\130\6\10\0" - + "\51\6\1\7\1\6\5\0\106\6\12\0\37\6\1\0\14\7\4\0" - + "\14\7\12\0\12\7\36\6\2\0\5\6\13\0\54\6\4\0\21\7" - + "\7\6\2\7\6\0\12\7\46\0\27\6\5\7\4\0\65\6\12\7" - + "\1\0\35\7\2\0\13\7\6\0\12\7\15\0\1\6\10\0\16\7" - + "\102\0\5\7\57\6\21\7\7\6\4\0\12\7\21\0\11\7\14\0" - + "\3\7\36\6\15\7\2\6\12\7\54\6\16\7\14\0\44\6\24\7" - + "\10\0\12\7\3\0\3\6\12\7\44\6\122\0\3\7\1\0\25\7" - + "\4\6\1\7\4\6\3\7\2\6\1\0\2\7\6\0\300\6\66\7" - + "\6\0\4\7\u0116\6\2\0\6\6\2\0\46\6\2\0\6\6\2\0" - + "\10\6\1\0\1\6\1\0\1\6\1\0\1\6\1\0\37\6\2\0" - + "\65\6\1\0\7\6\1\0\1\6\3\0\3\6\1\0\7\6\3\0" - + "\4\6\2\0\6\6\4\0\15\6\5\0\3\6\1\0\7\6\3\0" - + "\14\0\2\0\32\0\1\113\1\113\25\0\2\7\23\0\1\7\33\0" - + "\1\0\1\6\15\0\1\6\20\0\15\6\63\0\15\7\4\0\1\7" - + "\3\0\14\7\21\0\1\6\4\0\1\6\2\0\12\6\1\0\1\6" - + "\3\0\5\6\6\0\1\6\1\0\1\6\1\0\1\6\1\0\4\6" - + "\1\0\13\6\2\0\4\6\5\0\5\6\4\0\1\6\21\0\43\7" - + "\2\6\4\7\7\0\u0a70\0\57\6\1\0\57\6\1\0\205\6\6\0" - + "\4\6\3\7\2\6\14\0\46\6\1\0\1\6\5\0\1\6\2\0" - + "\70\6\7\0\1\6\17\0\1\7\27\6\11\0\7\6\1\0\7\6" - + "\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6" - + "\1\0\7\6\1\0\40\7\57\0\1\6\u01c0\0\21\0\4\0\2\6" - + "\1\7\31\0\17\7\1\0\5\6\2\0\3\7\2\6\4\0\126\6" - + "\2\0\2\7\2\0\3\6\1\0\132\6\1\0\4\6\5\0\51\6" - + "\3\0\136\6\21\0\33\6\65\0\20\6\u0200\0\u19b6\6\112\0\u51cd\6" - + "\63\0\u048d\6\103\0\56\6\2\0\u010d\6\3\0\20\6\12\7\2\6" - + "\24\0\57\6\1\7\4\0\12\7\1\0\37\6\1\0\1\7\106\6" - + "\14\7\45\0\11\6\2\0\147\6\2\0\4\6\1\0\36\6\2\0" - + "\2\6\105\0\13\6\1\7\3\6\1\7\4\6\1\7\27\6\5\7" - + "\30\0\64\6\14\0\2\7\62\6\21\7\13\0\12\7\6\0\22\7" - + "\6\6\3\0\1\6\4\0\12\7\34\6\10\7\2\0\27\6\15\7" - + "\14\0\35\6\3\0\4\7\57\6\16\7\16\0\1\6\12\7\6\0" - + "\5\6\1\7\12\6\12\7\5\6\1\0\51\6\16\7\11\0\3\6" - + "\1\7\10\6\2\7\2\0\12\7\6\0\27\6\3\0\1\6\3\7" - + "\62\6\1\7\1\6\3\7\2\6\2\7\5\6\2\7\1\6\1\7" - + "\1\6\30\0\3\6\2\0\13\6\5\7\2\0\3\6\2\7\12\0" - + "\6\6\2\0\6\6\2\0\6\6\11\0\7\6\1\0\7\6\1\0" - + "\53\6\1\0\4\6\4\0\2\6\132\0\43\6\10\7\1\0\2\7" - + "\2\0\12\7\6\0\u2ba4\6\14\0\27\6\4\0\61\6\4\0\u1800\0" - + "\u0900\0\u016e\6\2\0\152\6\46\0\7\6\14\0\5\6\5\0\1\6" - + "\1\7\12\6\1\0\15\6\1\0\5\6\1\0\1\6\1\0\2\6" - + "\1\0\2\6\1\0\154\6\41\0\u016b\6\22\0\100\6\2\0\66\6" - + "\10\0\40\0\14\6\4\0\20\7\20\0\16\7\5\0\2\7\30\0" - + "\3\7\40\0\5\6\1\0\207\6\23\0\12\7\7\0\32\6\4\0" - + "\1\7\1\0\32\6\13\0\131\6\3\0\6\6\2\0\6\6\2\0" - + "\6\6\2\0\3\6\41\0\2\0\14\6\1\0\32\6\1\0\23\6" - + "\1\0\2\6\1\0\17\6\2\0\16\6\42\0\173\6\105\0\65\7" - + "\210\0\1\7\202\0\35\6\3\0\61\6\17\0\1\7\37\0\40\6" - + "\20\0\21\6\1\7\10\6\1\7\5\0\46\6\5\7\5\0\36\6" - + "\2\0\44\6\4\0\10\6\1\0\5\7\52\0\236\6\2\0\12\7" - + "\126\0\50\6\10\0\64\6\234\0\u0137\6\11\0\26\6\12\0\10\6" - + "\230\0\6\6\2\0\1\6\1\0\54\6\1\0\2\6\3\0\1\6" - + "\2\0\27\6\12\0\27\6\11\0\37\6\141\0\26\6\12\0\32\6" - + "\106\0\70\6\6\0\2\6\100\0\1\6\3\7\1\0\2\7\5\0" - + "\4\7\4\6\1\0\3\6\1\0\33\6\4\0\3\7\4\0\1\7" - + "\40\0\35\6\3\0\35\6\43\0\10\6\1\0\34\6\2\7\31\0" - + "\66\6\12\0\26\6\12\0\23\6\15\0\22\6\156\0\111\6\u03b7\0" - + "\3\7\65\6\17\7\37\0\12\7\17\0\4\7\55\6\13\7\25\0" - + "\31\6\7\0\12\7\6\0\3\7\44\6\16\7\1\0\12\7\20\0" - + "\43\6\1\7\2\0\1\6\11\0\3\7\60\6\16\7\4\6\13\0" - + "\12\7\1\6\45\0\22\6\1\0\31\6\14\7\170\0\57\6\14\7" - + "\5\0\12\7\7\0\3\7\1\0\10\6\2\0\2\6\2\0\26\6" - + "\1\0\7\6\1\0\2\6\1\0\5\6\2\0\1\7\1\6\7\7" - + "\2\0\2\7\2\0\3\7\11\0\1\7\5\0\5\6\2\7\2\0" - + "\7\7\3\0\5\7\u010b\0\60\6\24\7\2\6\1\0\1\6\10\0" - + "\12\7\246\0\57\6\7\7\2\0\11\7\77\0\60\6\21\7\3\0" - + "\1\6\13\0\12\7\46\0\53\6\15\7\10\0\12\7\u01d6\0\100\6" - + "\12\7\25\0\1\6\u01c0\0\71\6\u0507\0\u0399\6\147\0\157\7\u0b91\0" - + "\u042f\6\u33d1\0\u0239\6\7\0\37\6\1\0\12\7\146\0\36\6\2\0" - + "\5\7\13\0\60\6\7\7\11\0\4\6\14\0\12\7\11\0\25\6" - + "\5\0\23\6\u0370\0\105\6\13\0\1\6\56\7\20\0\4\7\15\6" - + "\u4060\0\2\6\u0bfe\0\153\6\5\0\15\6\3\0\11\6\7\0\12\6" - + "\3\0\2\7\u14c6\0\5\7\3\0\6\7\10\0\10\7\2\0\7\7" - + "\36\0\4\7\224\0\3\7\u01bb\0\125\6\1\0\107\6\1\0\2\6" - + "\2\0\1\6\2\0\2\6\2\0\4\6\1\0\14\6\1\0\1\6" - + "\1\0\7\6\1\0\101\6\1\0\4\6\2\0\10\6\1\0\7\6" - + "\1\0\34\6\1\0\4\6\1\0\5\6\1\0\1\6\3\0\7\6" - + "\1\0\u0154\6\2\0\31\6\1\0\31\6\1\0\37\6\1\0\31\6" - + "\1\0\37\6\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6" - + "\1\0\31\6\1\0\10\6\2\0\62\7\u1000\0\305\6\13\0\7\7" - + "\u0529\0\4\6\1\0\33\6\1\0\2\6\1\0\1\6\2\0\1\6" - + "\1\0\12\6\1\0\4\6\1\0\1\6\1\0\1\6\6\0\1\6" - + "\4\0\1\6\1\0\1\6\1\0\1\6\1\0\3\6\1\0\2\6" - + "\1\0\1\6\2\0\1\6\1\0\1\6\1\0\1\6\1\0\1\6" - + "\1\0\1\6\1\0\2\6\1\0\1\6\2\0\4\6\1\0\7\6" - + "\1\0\4\6\1\0\4\6\1\0\1\6\1\0\12\6\1\0\21\6" - + "\5\0\3\6\1\0\5\6\1\0\21\6\u1144\0\ua6d7\6\51\0\u1035\6" - + "\13\0\336\6\u3fe2\0\u021e\6\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\u06ed\0" - + "\360\7\uffff\0\uffff\0\ufe12\0"; - - /** - * Translates characters to character classes - */ - private static final char[] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int[] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 - = "\13\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7" - + "\1\10\1\11\1\12\1\13\1\14\1\15\1\16\1\17" - + "\1\20\1\21\1\22\1\23\1\15\2\6\1\24\1\25" - + "\21\6\1\26\1\27\1\30\1\31\1\32\1\33\1\34" - + "\1\35\1\36\1\37\1\40\1\41\1\42\2\43\1\44" - + "\1\1\1\42\2\45\2\46\1\42\2\1\1\47\1\50" - + "\1\1\1\51\2\1\1\52\1\1\1\53\2\42\2\54" - + "\2\42\1\55\1\42\1\1\1\56\1\3\1\0\1\57" - + "\1\60\1\61\1\62\1\63\1\64\1\65\1\66\1\67" - + "\1\70\1\71\1\72\1\73\1\74\1\75\1\76\1\0" - + "\1\77\1\63\1\100\1\0\2\100\7\6\1\101\1\102" - + "\2\6\1\103\16\6\1\104\1\105\1\106\4\6\1\107" - + "\13\6\1\110\1\111\1\112\1\113\1\114\1\115\1\116" - + "\1\117\1\120\1\116\1\121\1\122\1\123\1\124\1\125" - + "\1\126\1\116\1\127\1\0\1\130\1\0\1\131\1\0" - + "\1\132\1\133\1\0\1\134\4\0\1\135\2\0\1\136" - + "\4\137\2\3\2\0\1\140\1\141\1\142\1\143\1\144" - + "\1\0\1\63\1\145\2\146\1\100\1\6\1\147\13\6" - + "\1\150\4\6\1\151\4\6\1\152\6\6\1\153\12\6" - + "\1\154\1\6\1\155\1\6\1\156\3\0\1\134\1\157" - + "\1\160\1\0\1\161\2\0\1\162\1\163\1\164\1\0" - + "\1\165\1\146\1\100\4\6\1\166\1\167\2\6\1\170" - + "\12\6\1\171\1\172\1\6\1\173\11\6\1\174\5\6" - + "\1\175\1\6\1\176\2\0\1\177\1\200\1\0\1\146" - + "\1\100\1\201\1\202\2\6\1\203\1\6\1\204\1\205" - + "\1\6\1\206\1\6\1\207\4\6\1\210\11\6\1\211" - + "\5\6\1\0\1\146\1\100\3\6\1\212\1\6\1\213" - + "\1\214\1\6\1\215\1\6\1\216\3\6\1\217\3\6" - + "\1\220\4\6\1\221\1\6\1\0\1\146\1\100\1\222" - + "\1\6\1\223\10\6\1\224\1\225\1\6\1\226\1\227" - + "\1\6\1\0\1\146\1\100\1\230\1\231\1\232\3\6" - + "\1\233\3\6\1\234\1\0\1\146\1\100\1\235\1\6" - + "\1\236\1\6\1\237\1\240\1\241\1\146\1\100\1\242" - + "\1\243\6\100"; - - private static int[] zzUnpackAction() { - int[] result = new int[446]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAction(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } - - /** - * Translates a state to a row index in the transition table - */ - private static final int[] ZZ_ROWMAP = zzUnpackRowMap(); - - private static final String ZZ_ROWMAP_PACKED_0 - = "\0\0\0\114\0\230\0\344\0\u0130\0\u017c\0\u01c8\0\u0214" - + "\0\u0260\0\u02ac\0\u02f8\0\u0344\0\u0390\0\u0344\0\u03dc\0\u0428" - + "\0\u0474\0\u04c0\0\u050c\0\u0558\0\u05a4\0\u05f0\0\u063c\0\u0688" - + "\0\u06d4\0\u0344\0\u0344\0\u0344\0\u0720\0\u0344\0\u0344\0\u076c" - + "\0\u07b8\0\u0804\0\u0850\0\u0344\0\u089c\0\u08e8\0\u0934\0\u0980" - + "\0\u09cc\0\u0a18\0\u0a64\0\u0ab0\0\u0afc\0\u0b48\0\u0b94\0\u0be0" - + "\0\u0c2c\0\u0c78\0\u0cc4\0\u0d10\0\u0d5c\0\u0344\0\u0344\0\u0344" - + "\0\u0344\0\u0344\0\u0344\0\u0344\0\u0da8\0\u0df4\0\u0e40\0\u0e8c" - + "\0\u0344\0\u0ed8\0\u0f24\0\u0344\0\u0344\0\u0f70\0\u0fbc\0\u1008" - + "\0\u0344\0\u1054\0\u0344\0\u10a0\0\u10ec\0\u1138\0\u0344\0\u0344" - + "\0\u1184\0\u0344\0\u11d0\0\u121c\0\u0344\0\u1268\0\u0344\0\u0344" - + "\0\u12b4\0\u1300\0\u0344\0\u134c\0\u1398\0\u0344\0\u13e4\0\u1430" - + "\0\u0344\0\u147c\0\u14c8\0\u0344\0\u0344\0\u1514\0\u0344\0\u1560" - + "\0\u0344\0\u15ac\0\u15f8\0\u0344\0\u0344\0\u1644\0\u0344\0\u0344" - + "\0\u1690\0\u0344\0\u0344\0\u16dc\0\u1728\0\u1774\0\u17c0\0\u180c" - + "\0\u1858\0\u18a4\0\u18f0\0\u193c\0\u1988\0\u19d4\0\u1a20\0\u1a6c" - + "\0\u1ab8\0\u0344\0\u0344\0\u1b04\0\u1b50\0\u04c0\0\u1b9c\0\u1be8" - + "\0\u1c34\0\u1c80\0\u1ccc\0\u1d18\0\u1d64\0\u1db0\0\u1dfc\0\u1e48" - + "\0\u1e94\0\u1ee0\0\u1f2c\0\u1f78\0\u04c0\0\u04c0\0\u1fc4\0\u2010" - + "\0\u205c\0\u20a8\0\u20f4\0\u04c0\0\u2140\0\u218c\0\u21d8\0\u2224" - + "\0\u2270\0\u22bc\0\u2308\0\u2354\0\u23a0\0\u23ec\0\u2438\0\u0344" - + "\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344" - + "\0\u2484\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u24d0" - + "\0\u0344\0\u1138\0\u0344\0\u1184\0\u0344\0\u11d0\0\u0344\0\u0344" - + "\0\u1268\0\u251c\0\u2568\0\u25b4\0\u2600\0\u264c\0\u2698\0\u26e4" - + "\0\u2730\0\u0344\0\u0344\0\u2484\0\u24d0\0\u277c\0\u27c8\0\u0344" - + "\0\u2814\0\u2860\0\u0344\0\u0344\0\u0344\0\u28ac\0\u0344\0\u28f8" - + "\0\u28f8\0\u0344\0\u2944\0\u180c\0\u2990\0\u29dc\0\u04c0\0\u2a28" - + "\0\u2a74\0\u2ac0\0\u2b0c\0\u2b58\0\u2ba4\0\u2bf0\0\u2c3c\0\u2c88" - + "\0\u2cd4\0\u2d20\0\u04c0\0\u2d6c\0\u2db8\0\u2e04\0\u2e50\0\u04c0" - + "\0\u2e9c\0\u2ee8\0\u2f34\0\u2f80\0\u04c0\0\u2fcc\0\u3018\0\u3064" - + "\0\u30b0\0\u30fc\0\u3148\0\u04c0\0\u3194\0\u31e0\0\u322c\0\u3278" - + "\0\u32c4\0\u3310\0\u335c\0\u33a8\0\u33f4\0\u3440\0\u04c0\0\u348c" - + "\0\u04c0\0\u34d8\0\u04c0\0\u3524\0\u3570\0\u251c\0\u0344\0\u0344" - + "\0\u0344\0\u35bc\0\u0344\0\u3608\0\u3654\0\u36a0\0\u0344\0\u0344" - + "\0\u36ec\0\u0344\0\u3738\0\u3784\0\u37d0\0\u381c\0\u3868\0\u38b4" - + "\0\u04c0\0\u04c0\0\u3900\0\u394c\0\u04c0\0\u3998\0\u39e4\0\u3a30" - + "\0\u3a7c\0\u3ac8\0\u3b14\0\u3b60\0\u3bac\0\u3bf8\0\u3c44\0\u04c0" - + "\0\u04c0\0\u3c90\0\u04c0\0\u3cdc\0\u3d28\0\u3d74\0\u3dc0\0\u3e0c" - + "\0\u3e58\0\u3ea4\0\u3ef0\0\u3f3c\0\u04c0\0\u3f88\0\u3fd4\0\u4020" - + "\0\u406c\0\u40b8\0\u04c0\0\u4104\0\u0344\0\u2484\0\u4150\0\u0344" - + "\0\u0344\0\u419c\0\u41e8\0\u4234\0\u04c0\0\u4280\0\u42cc\0\u4318" - + "\0\u04c0\0\u4364\0\u04c0\0\u04c0\0\u43b0\0\u04c0\0\u43fc\0\u04c0" - + "\0\u4448\0\u4494\0\u44e0\0\u452c\0\u04c0\0\u4578\0\u45c4\0\u4610" - + "\0\u465c\0\u46a8\0\u46f4\0\u4740\0\u478c\0\u47d8\0\u04c0\0\u4824" - + "\0\u4870\0\u48bc\0\u4908\0\u4954\0\u49a0\0\u49ec\0\u4a38\0\u4a84" - + "\0\u4ad0\0\u4b1c\0\u04c0\0\u4b68\0\u04c0\0\u04c0\0\u4bb4\0\u04c0" - + "\0\u4c00\0\u04c0\0\u4c4c\0\u4c98\0\u4ce4\0\u04c0\0\u4d30\0\u4d7c" - + "\0\u4dc8\0\u04c0\0\u4e14\0\u4e60\0\u4eac\0\u4ef8\0\u04c0\0\u4f44" - + "\0\u4f90\0\u4fdc\0\u5028\0\u04c0\0\u5074\0\u04c0\0\u50c0\0\u510c" - + "\0\u5158\0\u51a4\0\u51f0\0\u523c\0\u5288\0\u52d4\0\u04c0\0\u04c0" - + "\0\u5320\0\u04c0\0\u04c0\0\u536c\0\u53b8\0\u5404\0\u5450\0\u04c0" - + "\0\u04c0\0\u04c0\0\u549c\0\u54e8\0\u5534\0\u04c0\0\u5580\0\u55cc" - + "\0\u5618\0\u04c0\0\u5664\0\u56b0\0\u56fc\0\u04c0\0\u5748\0\u04c0" - + "\0\u5794\0\u04c0\0\u04c0\0\u0344\0\u0344\0\u57e0\0\u04c0\0\u04c0" - + "\0\u582c\0\u5878\0\u58c4\0\u5910\0\u595c\0\u1774"; - - private static int[] zzUnpackRowMap() { - int[] result = new int[446]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackRowMap(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); - } - return j; - } - - /** - * The transition table of the DFA - */ - private static final int[] ZZ_TRANS = zzUnpackTrans(); - - private static final String ZZ_TRANS_PACKED_0 - = "\1\14\1\15\1\16\1\17\1\20\1\21\1\22\1\14" - + "\1\22\1\23\1\24\1\17\1\25\1\26\1\27\1\30" - + "\1\22\1\31\1\14\1\32\1\33\4\22\1\34\1\35" - + "\1\36\1\37\1\40\2\22\1\41\2\31\1\22\1\42" - + "\1\43\1\14\1\44\1\45\1\46\1\47\1\22\1\50" - + "\1\51\1\52\1\53\1\54\1\55\1\56\1\57\1\22" - + "\1\60\1\22\1\61\2\22\1\62\1\63\1\64\1\65" - + "\1\66\1\67\1\70\1\71\1\72\1\73\1\74\1\75" - + "\1\76\1\77\1\100\1\101\1\22\1\14\1\102\1\103" - + "\1\104\30\102\1\105\12\102\1\106\45\102\1\107\1\110" - + "\1\111\31\107\1\105\11\107\1\106\45\107\1\14\1\112" - + "\1\113\1\114\1\115\3\14\1\116\2\14\1\114\2\14" - + "\1\117\2\116\4\14\4\116\5\14\3\116\2\14\2\116" - + "\3\14\26\116\2\14\1\120\46\14\1\121\44\14\1\122" - + "\14\14\1\112\1\113\1\114\4\14\1\123\2\14\1\114" - + "\3\14\2\123\2\14\1\124\1\14\4\123\5\14\3\123" - + "\2\14\2\123\3\14\26\123\2\14\1\125\46\14\1\126" - + "\44\14\1\127\13\14\1\130\1\112\1\113\26\130\1\131" - + "\63\130\1\132\1\133\12\130\1\134\77\130\1\112\1\113" - + "\7\130\1\135\65\130\1\136\13\130\1\137\1\110\1\111" - + "\43\137\1\140\1\141\44\137\116\0\1\16\114\0\1\17" - + "\7\0\1\17\104\0\1\142\1\143\24\0\1\144\113\0" - + "\1\145\67\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\26\22\14\0\1\22\12\0\1\146\1\147" - + "\6\0\1\150\13\0\1\150\3\0\2\150\33\0\1\151" - + "\25\0\1\152\1\0\1\153\4\0\2\152\4\0\4\152" - + "\1\0\1\154\3\0\3\152\2\0\2\152\3\0\26\152" - + "\2\0\1\155\45\0\1\156\76\0\1\157\14\0\1\160" - + "\77\0\1\161\13\0\1\162\100\0\1\163\105\0\1\150" - + "\7\0\1\31\13\0\1\31\3\0\2\31\2\164\101\0" - + "\1\165\72\0\1\150\7\0\1\166\13\0\1\167\2\170" - + "\1\0\1\171\1\172\2\164\55\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\2\22\1\173\3\22" - + "\1\174\2\22\1\175\1\176\13\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\1\22\1\177" - + "\6\22\3\0\2\22\1\200\11\22\1\201\11\22\14\0" - + "\1\22\33\0\1\202\12\0\1\203\54\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\1\22\1\204" - + "\24\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\205\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\5\22\1\206\20\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22" - + "\1\207\3\22\1\210\5\22\1\211\11\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\212\3\0\10\22\1\213\1\22\1\214\2\22\1\215" - + "\10\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\22\22\1\216\3\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\217\3\0\2\22\1\220\7\22\1\221\13\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\1\22\1\222\14\22\1\223\1\22" - + "\1\224\5\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\3\22\1\225\4\22\3\0\5\22" - + "\1\226\1\22\1\227\11\22\1\230\4\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\5\22\1\231\1\22\1\232\16\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\233\3\0\6\22\1\234\11\22\1\235\5\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\11\22\1\236\4\22\1\237\7\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\1\22\1\240\1\241\7\22\1\242\13\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\2\22\1\243\3\22\1\244\17\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\245\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\7\22\1\246\16\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\2\22\1\247" - + "\23\22\14\0\1\22\33\0\1\250\52\0\1\251\40\0" - + "\1\252\53\0\1\253\37\0\1\254\113\0\1\255\61\0" - + "\1\102\2\0\30\102\1\0\12\102\1\0\45\102\2\0" - + "\1\104\111\0\1\256\3\0\27\256\1\257\1\260\1\256" - + "\1\261\1\256\1\262\5\256\1\263\1\256\1\264\1\265" - + "\5\256\1\266\1\267\1\256\1\270\30\256\1\0\1\107" - + "\2\0\31\107\1\0\11\107\1\0\45\107\2\0\1\111" - + "\113\0\1\113\114\0\1\114\7\0\1\114\116\0\1\271" - + "\105\0\2\272\3\0\1\272\1\0\4\272\2\0\4\272" - + "\1\0\1\273\2\0\10\272\3\0\26\272\16\0\1\274" - + "\2\0\30\274\1\275\60\274\10\0\2\276\3\0\1\276" - + "\1\0\4\276\2\0\4\276\1\0\1\277\2\0\10\276" - + "\3\0\26\276\34\0\1\300\75\0\1\301\2\0\30\301" - + "\1\302\1\303\57\301\31\0\1\304\64\0\1\133\126\0" - + "\1\305\102\0\1\306\3\0\1\307\3\0\1\310\2\0" - + "\2\307\2\0\1\311\1\0\4\307\5\0\3\307\2\0" - + "\2\307\3\0\26\307\2\0\1\312\13\0\1\137\2\0" - + "\43\137\2\0\44\137\1\313\3\0\32\313\1\314\1\313" - + "\1\262\5\313\1\263\1\313\1\264\1\265\5\313\1\266" - + "\1\267\1\313\1\315\27\313\1\316\1\0\1\142\1\317" - + "\1\320\111\142\5\321\1\322\106\321\11\0\1\323\123\0" - + "\1\150\13\0\1\150\3\0\2\150\2\164\57\0\2\152" - + "\3\0\1\152\1\0\4\152\2\0\4\152\4\0\10\152" - + "\3\0\26\152\50\0\1\324\113\0\1\325\77\0\1\326" - + "\13\0\1\327\76\0\1\330\3\0\1\331\13\0\1\331" - + "\3\0\2\331\2\0\1\330\100\0\1\332\72\0\1\150" - + "\7\0\1\166\13\0\1\166\3\0\2\166\2\164\60\0" - + "\1\150\7\0\1\166\13\0\1\167\3\0\1\171\1\172" - + "\2\164\67\0\2\333\3\0\3\333\5\0\1\334\2\0" - + "\5\333\3\0\1\333\1\0\1\333\1\0\1\333\6\0" - + "\1\333\41\0\1\150\7\0\1\166\13\0\1\172\3\0" - + "\2\172\2\164\60\0\1\150\7\0\1\166\13\0\1\335" - + "\3\0\2\335\2\164\55\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\14\22\1\336\11\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\1\22\1\337\24\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\7\22\1\340\16\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\7\22\1\341" - + "\16\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\10\22\1\342\15\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\343\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\5\22\1\344\20\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\7\22\1\345\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\10\22\1\346\15\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\5\22\1\347\2\22\1\350\15\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\7\22\1\351\16\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22" - + "\1\352\23\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\10\22\1\353\15\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\2\22\1\354\23\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\17\22\1\355\6\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\11\22" - + "\1\356\14\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\7\22\1\357\3\0\26\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\15\22\1\360\10\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\10\22\1\361\10\22\1\362\4\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\14\22\1\363\11\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\12\22\1\364" - + "\5\22\1\365\5\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\1\22\1\366" - + "\7\22\1\367\14\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\17\22\1\370" - + "\6\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\5\22\1\371\2\22\1\372" - + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\17\22\1\373\6\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\374\3\0\26\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\13\22" - + "\1\375\12\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\3\22\1\376\4\22\3\0\14\22" - + "\1\377\11\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\7\22\1\u0100\16\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\10\22\1\u0101\15\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\11\22\1\u0102\14\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\6\22" - + "\1\u0103\2\22\1\u0104\14\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\4\22" - + "\1\u0105\21\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\1\u0106\25\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\1\22\1\u0107\24\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\11\22\1\u0108\14\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u0109" - + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\3\22\1\u010a\4\22\3\0\26\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\25\22\1\u010b\14\0\1\22\21\0\2\u010c" - + "\3\0\3\u010c\5\0\1\u010c\2\0\5\u010c\3\0\1\u010c" - + "\1\0\1\u010c\1\0\1\u010c\6\0\1\u010c\50\0\2\u010d" - + "\3\0\3\u010d\5\0\1\u010d\2\0\5\u010d\3\0\1\u010d" - + "\1\0\1\u010d\1\0\1\u010d\6\0\1\u010d\30\0\1\u010e" - + "\2\0\30\u010e\1\302\1\0\57\u010e\1\303\2\0\30\303" - + "\1\u010f\60\303\16\0\1\u0110\113\0\1\u0111\105\0\1\u0112" - + "\6\0\2\u0112\4\0\4\u0112\5\0\3\u0112\2\0\2\u0112" - + "\3\0\26\u0112\2\0\1\u0113\23\0\2\307\3\0\1\307" - + "\1\0\4\307\2\0\4\307\4\0\10\307\3\0\26\307" - + "\33\0\1\u0114\6\0\1\u0115\77\0\1\u0116\6\0\2\u0116" - + "\4\0\4\u0116\5\0\3\u0116\2\0\2\u0116\3\0\26\u0116" - + "\2\0\1\u0117\62\0\1\u0118\46\0\1\320\111\0\5\321" - + "\1\u0119\106\321\4\0\1\320\1\322\140\0\1\u011a\102\0" - + "\1\331\13\0\1\331\3\0\2\331\71\0\2\u011b\3\0" - + "\3\u011b\5\0\1\u011b\2\0\5\u011b\3\0\1\u011b\1\0" - + "\1\u011b\1\0\1\u011b\6\0\1\u011b\41\0\1\150\7\0" - + "\1\166\13\0\1\u011c\3\0\2\u011c\2\164\55\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\5\22" - + "\1\u011d\20\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u011e\23\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\4\22\1\u011f\21\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\u0120\3\0\26\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\16\22\1\u0121" - + "\7\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\u0122\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\2\22\1\u0123\23\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\12\22" - + "\1\u0124\13\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\7\22\1\u0125\3\0\26\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\u0126\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\5\22\1\u0127\2\22\1\u0128\15\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\5\22\1\u0129\20\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u012a" - + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\u012b\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\10\22\1\u012c\15\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\1\22" - + "\1\u012d\24\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\11\22\1\u012e\14\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\u012f\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\14\22\1\u0130\11\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\7\22\1\u0131\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\6\22\1\u0132\17\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\5\22\1\u0133\20\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u0134\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\10\22\1\u0135\15\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\u0136\3\0\26\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\6\22" - + "\1\u0137\5\22\1\u0138\11\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u0139\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\2\22\1\u013a\23\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\u013b\3\0\26\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22" - + "\1\u013c\23\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\16\22\1\u013d\7\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\14\22\1\u013e\11\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\10\22\1\u013f\15\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\22\22" - + "\1\u0140\3\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\3\22\1\u0141\22\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\14\22\1\u0142\11\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\13\22\1\u0143\12\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\11\22" - + "\1\u0144\14\22\14\0\1\22\21\0\2\u0145\3\0\3\u0145" - + "\5\0\1\u0145\2\0\5\u0145\3\0\1\u0145\1\0\1\u0145" - + "\1\0\1\u0145\6\0\1\u0145\50\0\2\u0146\3\0\3\u0146" - + "\5\0\1\u0146\2\0\5\u0146\3\0\1\u0146\1\0\1\u0146" - + "\1\0\1\u0146\6\0\1\u0146\31\0\2\u0147\5\0\2\u0112" - + "\1\0\1\u0147\1\0\1\u0112\1\u0148\4\u0112\2\0\4\u0112" - + "\4\0\10\u0112\3\0\26\u0112\33\0\1\u0149\123\0\1\u014a" - + "\76\0\2\u0116\3\0\1\u0116\1\0\4\u0116\2\0\4\u0116" - + "\4\0\10\u0116\3\0\26\u0116\16\0\4\321\1\320\1\u0119" - + "\106\321\20\0\2\u014b\3\0\3\u014b\5\0\1\u014b\2\0" - + "\5\u014b\3\0\1\u014b\1\0\1\u014b\1\0\1\u014b\6\0" - + "\1\u014b\41\0\1\150\7\0\1\166\13\0\1\u014c\3\0" - + "\2\u014c\2\164\55\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\u014d\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\14\22\1\u014e\11\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u014f" - + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\7\22\1\u0150\16\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\3\22\1\u0151\22\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\1\22\1\u0152\24\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\16\22\1\u0153" - + "\7\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\10\22\1\u0154\15\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\11\22\1\u0155\14\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\5\22\1\u0156\20\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\11\22\1\u0157" - + "\14\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\1\22\1\u0158\24\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\u0159\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\1\22\1\u015a\24\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\22\22\1\u015b" - + "\3\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\5\22\1\u015c\20\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\15\22\1\u015d\10\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\6\22\1\u015e\17\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\2\22\1\u015f" - + "\23\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\1\22\1\u0160\24\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\1\22\1\u0161\24\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u0162" - + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\3\22\1\u0163\4\22\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\12\22\1\u0164\13\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\10\22\1\u0165\15\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\21\22" - + "\1\u0166\4\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\7\22\1\u0167\3\0\26\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\7\22\1\u0168\3\0\26\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22" - + "\1\u0169\23\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u016a\23\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\11\22\1\u016b\14\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\7\22\1\u016c\16\22\14\0\1\22\2\0\2\u0147" - + "\10\0\1\u0147\2\0\1\u0148\123\0\1\u016d\105\0\2\u016e" - + "\3\0\3\u016e\5\0\1\u016e\2\0\5\u016e\3\0\1\u016e" - + "\1\0\1\u016e\1\0\1\u016e\6\0\1\u016e\41\0\1\150" - + "\7\0\1\166\13\0\1\u016f\3\0\2\u016f\2\164\55\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\14\22\1\u0170\11\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\11\22\1\u0171" - + "\14\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\13\22\1\u0172\12\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\7\22\1\u0173\16\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\7\22\1\u0174\16\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\4\22\1\u0175" - + "\21\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\16\22\1\u0176\7\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\11\22\1\u0177\14\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u0178" - + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\17\22\1\u0179\6\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\3\22\1\u017a\4\22\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\7\22\1\u017b\16\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\3\22\1\u017c\4\22" - + "\3\0\7\22\1\u017d\16\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22" - + "\1\u017e\15\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\21\22\1\u017f\4\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\11\22\1\u0180\14\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\14\22\1\u0181\11\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u0182\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\11\22\1\u0183\14\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\u0184\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\10\22\1\u0185\15\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\23\22\1\u0186" - + "\2\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\4\22\1\u0187\21\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\11\22\1\u0188\14\22\14\0\1\22\30\0" - + "\1\u0189\104\0\2\u018a\3\0\3\u018a\5\0\1\u018a\2\0" - + "\5\u018a\3\0\1\u018a\1\0\1\u018a\1\0\1\u018a\6\0" - + "\1\u018a\41\0\1\150\7\0\1\166\13\0\1\u018b\3\0" - + "\2\u018b\2\164\55\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\20\22\1\u018c\5\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\6\22\1\u018d\17\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\5\22" - + "\1\u018e\20\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\12\22\1\u018f\13\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\13\22\1\u0190\12\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\2\22\1\u0191\23\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\4\22" - + "\1\u0192\21\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u0193\23\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\10\22\3\0\2\22\1\u0194\23\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\u0195\3\0\26\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\7\22\1\u0196" - + "\16\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\10\22\1\u0197\15\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\4\22\1\u0198\21\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\10\22\1\u0199\15\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\7\22\1\u019a\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\u019b\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\10\22\1\u019c\15\22\14\0\1\22\31\0\1\u019d\103\0" - + "\2\u019e\3\0\3\u019e\5\0\1\u019e\2\0\5\u019e\3\0" - + "\1\u019e\1\0\1\u019e\1\0\1\u019e\6\0\1\u019e\41\0" - + "\1\150\7\0\1\166\13\0\1\u019f\3\0\2\u019f\2\164" - + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\7\22\1\u01a0\16\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u01a1\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\u01a2\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\4\22\1\u01a3\21\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u01a4\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\4\22\1\u01a5\21\22\14\0" - + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0" - + "\10\22\3\0\14\22\1\u01a6\11\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\7\22\1\u01a7\16\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\7\22\1\u01a8\3\0\26\22" - + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22" - + "\4\0\7\22\1\u01a9\3\0\26\22\14\0\1\22\7\0" - + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0" - + "\20\22\1\u01aa\5\22\14\0\1\22\30\0\1\u01ab\104\0" - + "\2\u01ac\3\0\3\u01ac\5\0\1\u01ac\2\0\5\u01ac\3\0" - + "\1\u01ac\1\0\1\u01ac\1\0\1\u01ac\6\0\1\u01ac\41\0" - + "\1\150\7\0\1\166\13\0\1\u01ad\3\0\2\u01ad\2\164" - + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22" - + "\1\u01ae\3\0\26\22\14\0\1\22\7\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\10\22\3\0\6\22\1\u01af" - + "\17\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\7\22\1\u01b0\3\0\26\22\14\0\1\22" - + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22" - + "\3\0\10\22\1\u01b1\15\22\14\0\1\22\7\0\3\22" - + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\13\22" - + "\1\u01b2\12\22\14\0\1\22\7\0\3\22\7\0\2\22" - + "\3\0\4\22\4\0\10\22\3\0\13\22\1\u01b3\12\22" - + "\14\0\1\22\25\0\1\u01b4\107\0\2\u01b5\3\0\3\u01b5" - + "\5\0\1\u01b5\2\0\5\u01b5\3\0\1\u01b5\1\0\1\u01b5" - + "\1\0\1\u01b5\6\0\1\u01b5\41\0\1\150\7\0\1\166" - + "\13\0\1\u01b6\3\0\2\u01b6\2\164\55\0\3\22\7\0" - + "\2\22\3\0\4\22\4\0\3\22\1\u01b7\4\22\3\0" - + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0" - + "\4\22\4\0\10\22\3\0\5\22\1\u01b8\20\22\14\0" - + "\1\22\12\0\1\150\7\0\1\166\13\0\1\u01b9\3\0" - + "\2\u01b9\2\164\60\0\1\150\7\0\1\166\13\0\1\u01ba" - + "\3\0\2\u01ba\2\164\60\0\1\150\7\0\1\166\13\0" - + "\1\u01bb\3\0\2\u01bb\2\164\60\0\1\150\7\0\1\166" - + "\13\0\1\u01bc\3\0\2\u01bc\2\164\60\0\1\150\7\0" - + "\1\166\13\0\1\u01bd\3\0\2\u01bd\2\164\60\0\1\150" - + "\7\0\1\166\13\0\1\u01be\3\0\2\u01be\2\164\47\0"; - - private static int[] zzUnpackTrans() { - int[] result = new int[22952]; - int offset = 0; - offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackTrans(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - value--; - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } - - - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; - - private static final int ZZ_NO_MATCH = 1; - - private static final int ZZ_PUSHBACK_2BIG = 2; - - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; - - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute(); - - private static final String ZZ_ATTRIBUTE_PACKED_0 - = "\13\0\1\11\1\1\1\11\13\1\3\11\1\1\2\11" - + "\4\1\1\11\21\1\7\11\4\1\1\11\2\1\2\11" - + "\3\1\1\11\1\1\1\11\3\1\2\11\1\1\1\11" - + "\2\1\1\11\1\1\2\11\2\1\1\11\2\1\1\11" - + "\2\1\1\11\1\1\1\0\2\11\1\1\1\11\1\1" - + "\1\11\2\1\2\11\1\1\2\11\1\1\2\11\1\0" - + "\3\1\1\0\11\1\2\11\44\1\11\11\1\1\6\11" - + "\1\1\1\11\1\0\1\11\1\0\1\11\1\0\2\11" - + "\1\0\1\1\4\0\1\1\2\0\2\11\4\1\1\11" - + "\2\0\3\11\1\1\1\11\1\0\1\1\1\11\61\1" - + "\3\0\3\11\1\0\1\11\2\0\1\1\2\11\1\0" - + "\1\11\52\1\1\11\2\0\2\11\1\0\42\1\1\0" - + "\33\1\1\0\23\1\1\0\15\1\1\0\10\1\2\11" - + "\11\1"; - - private static int[] zzUnpackAttribute() { - int[] result = new int[446]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAttribute(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } - - /** - * the input device - */ - private java.io.Reader zzReader; - - /** - * the current state of the DFA - */ - private int zzState; - - /** - * the current lexical state - */ - private int zzLexicalState = YYINITIAL; - - /** - * this buffer contains the current text to be matched and is - * the source of the yytext() string - */ - private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - - /** - * the textposition at the last accepting state - */ - private int zzMarkedPos; - - /** - * the current text position in the buffer - */ - private int zzCurrentPos; - - /** - * startRead marks the beginning of the yytext() string in the buffer - */ - private int zzStartRead; - - /** - * endRead marks the last character in the buffer, that has been read - * from input - */ - private int zzEndRead; - - /** - * number of newlines encountered up to the start of the matched text - */ - private int yyline; - - /** - * the number of characters up to the start of the matched text - */ - private int yychar; - - /** - * the number of characters from the last newline up to the start of the - * matched text - */ - private int yycolumn; - - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; - - /** - * zzAtEOF == true <=> the scanner is at the EOF - */ - private boolean zzAtEOF; - - /** - * denotes if the user-EOF-code has already been executed - */ - private boolean zzEOFDone; - - /** - * The number of occupied positions in zzBuffer beyond zzEndRead. - * When a lead/high surrogate has been read from the input stream - * into the final zzBuffer position, this will have a value of 1; - * otherwise, it will have a value of 0. - */ - private int zzFinalHighSurrogate = 0; - - /* user code: */ - private String sourceCode; - - public ActionScriptLexer(String sourceCode) { - this(new StringReader(sourceCode)); - this.sourceCode = sourceCode; - } - - public void yypushbackstr(String s, int state) { - sourceCode = s + sourceCode.substring(yychar + yylength()); - yyreset(new StringReader(sourceCode)); - yybegin(state); - } - - public void yypushbackstr(String s) { - yypushbackstr(s, YYINITIAL); - } - - StringBuffer string = new StringBuffer(); - - private static String xmlTagName = ""; - - public int yychar() { - return yychar; - } - - private Stack pushedBack = new Stack<>(); - - public int yyline() { - return yyline + 1; - } - - private List listeners = new ArrayList<>(); - - public void addListener(LexListener listener) { - listeners.add(listener); - } - - public void removeListener(LexListener listener) { - listeners.remove(listener); - } - - public void informListenersLex(ParsedSymbol s) { - for (LexListener l : listeners) { - l.onLex(s); - } - } - - public void informListenersPushBack(ParsedSymbol s) { - for (LexListener l : listeners) { - l.onPushBack(s); - } - } - - public void pushback(ParsedSymbol symb) { - pushedBack.push(symb); - last = null; - informListenersPushBack(symb); - } - - ParsedSymbol last; - - public ParsedSymbol lex() throws java.io.IOException, AVM2ParseException { - ParsedSymbol ret = null; - if (!pushedBack.isEmpty()) { - ret = last = pushedBack.pop(); - } else { - ret = last = yylex(); - } - informListenersLex(ret); - return ret; - } - - /** - * Creates a new scanner - * - * @param in the java.io.Reader to read input from. - */ - public ActionScriptLexer(java.io.Reader in) { - this.zzReader = in; - } - - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char[] zzUnpackCMap(String packed) { - char[] map = new char[0x110000]; - int i = 0; /* index in packed string */ - - int j = 0; /* index in unpacked array */ - - while (i < 3140) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do { - map[j++] = value; - } while (--count > 0); - } - return map; - } - - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { - - /* first: make room (if you can) */ - if (zzStartRead > 0) { - zzEndRead += zzFinalHighSurrogate; - zzFinalHighSurrogate = 0; - System.arraycopy(zzBuffer, zzStartRead, - zzBuffer, 0, - zzEndRead - zzStartRead); - - /* translate stored positions */ - zzEndRead -= zzStartRead; - zzCurrentPos -= zzStartRead; - zzMarkedPos -= zzStartRead; - zzStartRead = 0; - } - - /* is the buffer big enough? */ - if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { - /* if not: blow it up */ - char newBuffer[] = new char[zzBuffer.length * 2]; - System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); - zzBuffer = newBuffer; - zzEndRead += zzFinalHighSurrogate; - zzFinalHighSurrogate = 0; - } - - /* fill the buffer with new input */ - int requested = zzBuffer.length - zzEndRead; - int totalRead = 0; - while (totalRead < requested) { - int numRead = zzReader.read(zzBuffer, zzEndRead + totalRead, requested - totalRead); - if (numRead == -1) { - break; - } - totalRead += numRead; - } - - if (totalRead > 0) { - zzEndRead += totalRead; - if (totalRead == requested) { /* possibly more input available */ - - if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { - --zzEndRead; - zzFinalHighSurrogate = 1; - } - } - return false; - } - - // totalRead = 0: End of stream - return true; - } - - /** - * Closes the input stream. - */ - public final void yyclose() throws java.io.IOException { - zzAtEOF = true; /* indicate end of file */ - - zzEndRead = zzStartRead; /* invalidate buffer */ - - if (zzReader != null) { - zzReader.close(); - } - } - - /** - * Resets the scanner to read from a new input stream. - * Does not close the old reader. - * - * All internal variables are reset, the old input stream - * cannot be reused (internal buffer is discarded and lost). - * Lexical state is set to ZZ_INITIAL. - * - * Internal scan buffer is resized down to its initial length, if it has - * grown. - * - * @param reader the new input stream - */ - public final void yyreset(java.io.Reader reader) { - zzReader = reader; - zzAtBOL = true; - zzAtEOF = false; - zzEOFDone = false; - zzEndRead = zzStartRead = 0; - zzCurrentPos = zzMarkedPos = 0; - zzFinalHighSurrogate = 0; - yyline = yychar = yycolumn = 0; - zzLexicalState = YYINITIAL; - if (zzBuffer.length > ZZ_BUFFERSIZE) { - zzBuffer = new char[ZZ_BUFFERSIZE]; - } - } - - /** - * Returns the current lexical state. - */ - public final int yystate() { - return zzLexicalState; - } - - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } - - /** - * Returns the text matched by the current regular expression. - */ - public final String yytext() { - return new String(zzBuffer, zzStartRead, zzMarkedPos - zzStartRead); - } - - /** - * Returns the character at position pos from the - * matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. - * A value from 0 to yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer[zzStartRead + pos]; - } - - /** - * Returns the length of the matched text region. - */ - public final int yylength() { - return zzMarkedPos - zzStartRead; - } - - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method - * will only be called with things that "Can't Possibly Happen". - * If this method is called, something is seriously wrong - * (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done - * in error fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; - } catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; - } - - throw new Error(message); - } - - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. - * This number must not be greater than yylength()! - */ - public void yypushback(int number) { - if (number > yylength()) { - zzScanError(ZZ_PUSHBACK_2BIG); - } - - zzMarkedPos -= number; - } - - /** - * Resumes scanning until the next regular expression is matched, - * the end of input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - */ - public ParsedSymbol yylex() throws java.io.IOException, AVM2ParseException { - int zzInput; - int zzAction; - - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - char[] zzBufferL = zzBuffer; - char[] zzCMapL = ZZ_CMAP; - - int[] zzTransL = ZZ_TRANS; - int[] zzRowMapL = ZZ_ROWMAP; - int[] zzAttrL = ZZ_ATTRIBUTE; - - while (true) { - zzMarkedPosL = zzMarkedPos; - - yychar += zzMarkedPosL - zzStartRead; - - zzAction = -1; - - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - - zzState = ZZ_LEXSTATE[zzLexicalState]; - - // set up zzAction for empty match case: - int zzAttributes = zzAttrL[zzState]; - if ((zzAttributes & 1) == 1) { - zzAction = zzState; - } - - zzForAction: - { - while (true) { - - if (zzCurrentPosL < zzEndReadL) { - zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); - zzCurrentPosL += Character.charCount(zzInput); - } else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } else { - zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); - zzCurrentPosL += Character.charCount(zzInput); - } - } - int zzNext = zzTransL[zzRowMapL[zzState] + zzCMapL[zzInput]]; - if (zzNext == -1) { - break zzForAction; - } - zzState = zzNext; - - zzAttributes = zzAttrL[zzState]; - if ((zzAttributes & 1) == 1) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ((zzAttributes & 8) == 8) { - break zzForAction; - } - } - - } - } - - // store back cached position - zzMarkedPos = zzMarkedPosL; - - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 1: { - } - case 164: - break; - case 2: { - yyline++; - } - case 165: - break; - case 3: { /*ignore*/ - - } - case 166: - break; - case 4: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); - } - case 167: - break; - case 5: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); - } - case 168: - break; - case 6: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); - } - case 169: - break; - case 7: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); - } - case 170: - break; - case 8: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); - } - case 171: - break; - case 9: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); - } - case 172: - break; - case 10: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); - } - case 173: - break; - case 11: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); - } - case 174: - break; - case 12: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); - } - case 175: - break; - case 13: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); - } - case 176: - break; - case 14: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); - } - case 177: - break; - case 15: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); - } - case 178: - break; - case 16: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); - } - case 179: - break; - case 17: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); - } - case 180: - break; - case 18: { - string.setLength(0); - yybegin(STRING); - } - case 181: - break; - case 19: { - string.setLength(0); - yybegin(CHARLITERAL); - } - case 182: - break; - case 20: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); - } - case 183: - break; - case 21: { - string.setLength(0); - yybegin(OIDENTIFIER); - } - case 184: - break; - case 22: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); - } - case 185: - break; - case 23: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); - } - case 186: - break; - case 24: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); - } - case 187: - break; - case 25: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); - } - case 188: - break; - case 26: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); - } - case 189: - break; - case 27: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); - } - case 190: - break; - case 28: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); - } - case 191: - break; - case 29: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); - } - case 192: - break; - case 30: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); - } - case 193: - break; - case 31: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); - } - case 194: - break; - case 32: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); - } - case 195: - break; - case 33: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); - } - case 196: - break; - case 34: { - string.append(yytext()); - } - case 197: - break; - case 35: { - yybegin(YYINITIAL); - yyline++; - } - case 198: - break; - case 36: { - yybegin(YYINITIAL); - // length also includes the trailing quote - return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); - } - case 199: - break; - case 37: { - yybegin(YYINITIAL); - yyline++; - } - case 200: - break; - case 38: { - string.append(yytext()); - yyline++; - } - case 201: - break; - case 39: { - yybegin(XML); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_END, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 202: - break; - case 40: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRNAMEVAR_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 203: - break; - case 41: { - yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRVALVAR_BEGIN, yytext()); - } - case 204: - break; - case 42: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRNAMEVAR_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 205: - break; - case 43: { - yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRVALVAR_BEGIN, yytext()); - } - case 206: - break; - case 44: { - string.append(yytext()); - yyline++; - } - case 207: - break; - case 45: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_VAR_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 208: - break; - case 46: { - yybegin(YYINITIAL); - // length also includes the trailing quote - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); - } - case 209: - break; - case 47: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); - } - case 210: - break; - case 48: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); - } - case 211: - break; - case 49: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DESCENDANTS, yytext()); - } - case 212: - break; - case 50: { - return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, yytext()); - } - case 213: - break; - case 51: { - return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); - } - case 214: - break; - case 52: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FILTER, yytext()); - } - case 215: - break; - case 53: { - yybegin(XMLOPENTAG); - string.setLength(0); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext()); - } - case 216: - break; - case 54: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); - } - case 217: - break; - case 55: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); - } - case 218: - break; - case 56: { - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext()); - } - case 219: - break; - case 57: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); - } - case 220: - break; - case 58: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); - } - case 221: - break; - case 59: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); - } - case 222: - break; - case 60: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); - } - case 223: - break; - case 61: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); - } - case 224: - break; - case 62: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); - } - case 225: - break; - case 63: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); - } - case 226: - break; - case 64: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); - } - case 227: - break; - case 65: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); - } - case 228: - break; - case 66: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); - } - case 229: - break; - case 67: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); - } - case 230: - break; - case 68: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IF, yytext()); - } - case 231: - break; - case 69: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); - } - case 232: - break; - case 70: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IN, yytext()); - } - case 233: - break; - case 71: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DO, yytext()); - } - case 234: - break; - case 72: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); - } - case 235: - break; - case 73: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); - } - case 236: - break; - case 74: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); - } - case 237: - break; - case 75: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); - } - case 238: - break; - case 76: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); - } - case 239: - break; - case 77: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); - } - case 240: - break; - case 78: { /* ignore illegal character escape */ - - } - case 241: - break; - case 79: { - string.append('\"'); - } - case 242: - break; - case 80: { - string.append('\''); - } - case 243: - break; - case 81: { - string.append('\f'); - } - case 244: - break; - case 82: { - string.append('\\'); - } - case 245: - break; - case 83: { - string.append('\b'); - } - case 246: - break; - case 84: { - string.append('\r'); - } - case 247: - break; - case 85: { - string.append('\n'); - } - case 248: - break; - case 86: { - string.append('\t'); - } - case 249: - break; - case 87: { - yybegin(XML); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTFINISHTAG_END, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 250: - break; - case 88: { - yybegin(XMLOPENTAGATTRIB); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTENAME, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 251: - break; - case 89: { - yybegin(XMLOPENTAG); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); - } - case 252: - break; - case 90: { - yybegin(XMLINSTRATTRIB); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTENAME, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 253: - break; - case 91: { - yybegin(XML); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTR_END, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 254: - break; - case 92: { - yybegin(XMLINSTROPENTAG); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); - } - case 255: - break; - case 93: { - yybegin(XMLOPENTAG); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 256: - break; - case 94: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 257: - break; - case 95: { - throw new AVM2ParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); - } - case 258: - break; - case 96: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); - } - case 259: - break; - case 97: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); - } - case 260: - break; - case 98: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); - } - case 261: - break; - case 99: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); - } - case 262: - break; - case 100: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); - } - case 263: - break; - case 101: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); - } - case 264: - break; - case 102: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); - } - case 265: - break; - case 103: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FOR, yytext()); - } - case 266: - break; - case 104: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.SET, yytext()); - } - case 267: - break; - case 105: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); - } - case 268: - break; - case 106: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRY, yytext()); - } - case 269: - break; - case 107: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.USE, yytext()); - } - case 270: - break; - case 108: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.VAR, yytext()); - } - case 271: - break; - case 109: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.GET, yytext()); - } - case 272: - break; - case 110: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); - } - case 273: - break; - case 111: { - string.append(yytext()); - yybegin(XML); - String ret = string.toString(); - string.setLength(0); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_CDATA, ret); - } - case 274: - break; - case 112: { - string.append(yytext()); - yybegin(XML); - String ret = string.toString(); - string.setLength(0); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_COMMENT, ret); - } - case 275: - break; - case 113: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHVARTAG_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 276: - break; - case 114: { - yybegin(XMLINSTROPENTAG); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTR_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 277: - break; - case 115: { - yybegin(YYINITIAL); - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRVARTAG_BEGIN, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 278: - break; - case 116: { - string.append('\u00A7'); - } - case 279: - break; - case 117: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); - } - case 280: - break; - case 118: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.EACH, yytext()); - } - case 281: - break; - case 119: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.ELSE, yytext()); - } - case 282: - break; - case 120: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CASE, yytext()); - } - case 283: - break; - case 121: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); - } - case 284: - break; - case 122: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); - } - case 285: - break; - case 123: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); - } - case 286: - break; - case 124: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WITH, yytext()); - } - case 287: - break; - case 125: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); - } - case 288: - break; - case 126: { - char val = (char) Integer.parseInt(yytext().substring(2), 16); - string.append(val); - } - case 289: - break; - case 127: { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHTAG, yytext())); - if (string.length() > 0) { - pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); - string.setLength(0); - } - return lex(); - } - case 290: - break; - case 128: { - String ret = string.toString(); - string.setLength(0); - string.append(yytext()); - yybegin(XMLCOMMENT); - if (!ret.isEmpty()) { - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, ret); - } - } - case 291: - break; - case 129: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); - } - case 292: - break; - case 130: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.FINAL, yytext()); - } - case 293: - break; - case 131: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.BREAK, yytext()); - } - case 294: - break; - case 132: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CATCH, yytext()); - } - case 295: - break; - case 133: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONST, yytext()); - } - case 296: - break; - case 134: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CLASS, yytext()); - } - case 297: - break; - case 135: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SUPER, yytext()); - } - case 298: - break; - case 136: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THROW, yytext()); - } - case 299: - break; - case 137: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WHILE, yytext()); - } - case 300: - break; - case 138: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.RETURN, yytext()); - } - case 301: - break; - case 139: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.STATIC, yytext()); - } - case 302: - break; - case 140: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SWITCH, yytext()); - } - case 303: - break; - case 141: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.NATIVE, yytext()); - } - case 304: - break; - case 142: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); - } - case 305: - break; - case 143: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPORT, yytext()); - } - case 306: - break; - case 144: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); - } - case 307: - break; - case 145: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PUBLIC, yytext()); - } - case 308: - break; - case 146: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FINALLY, yytext()); - } - case 309: - break; - case 147: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EXTENDS, yytext()); - } - case 310: - break; - case 148: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DEFAULT, yytext()); - } - case 311: - break; - case 149: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.DYNAMIC, yytext()); - } - case 312: - break; - case 150: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PRIVATE, yytext()); - } - case 313: - break; - case 151: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PACKAGE, yytext()); - } - case 314: - break; - case 152: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FUNCTION, yytext()); - } - case 315: - break; - case 153: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONTINUE, yytext()); - } - case 316: - break; - case 154: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.OVERRIDE, yytext()); - } - case 317: - break; - case 155: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERNAL, yytext()); - } - case 318: - break; - case 156: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); - } - case 319: - break; - case 157: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE, yytext()); - } - case 320: - break; - case 158: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERFACE, yytext()); - } - case 321: - break; - case 159: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); - } - case 322: - break; - case 160: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PROTECTED, yytext()); - } - case 323: - break; - case 161: { - String ret = string.toString(); - string.setLength(0); - string.append(yytext()); - yybegin(XMLCDATA); - if (!ret.isEmpty()) { - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, ret); - } - } - case 324: - break; - case 162: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); - } - case 325: - break; - case 163: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPLEMENTS, yytext()); - } - case 326: - break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - { - return new ParsedSymbol(SymbolGroup.EOF, SymbolType.EOF, null); - } - } else { - zzScanError(ZZ_NO_MATCH); - } - } - } - } -} +/* The following code was generated by JFlex 1.6.0 */ + +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + +/** + * This class is a scanner generated by + * JFlex 1.6.0 + * from the specification file C:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript3_script.flex + */ +public final class ActionScriptLexer { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + public static final int STRING = 2; + public static final int CHARLITERAL = 4; + public static final int XMLOPENTAG = 6; + public static final int XMLOPENTAGATTRIB = 8; + public static final int XMLINSTROPENTAG = 10; + public static final int XMLINSTRATTRIB = 12; + public static final int XMLCDATA = 14; + public static final int XMLCOMMENT = 16; + public static final int XML = 18; + public static final int OIDENTIFIER = 20; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, + 8, 8, 9, 9, 10, 10 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\13\1\2\1\113\1\3\1\1\22\0\1\13\1\14\1\33"+ + "\1\0\1\6\1\110\1\105\1\34\1\76\1\77\1\5\1\45\1\103"+ + "\1\15\1\11\1\4\1\35\3\41\4\42\2\21\1\17\1\102\1\12"+ + "\1\32\1\16\1\23\1\111\1\27\1\20\1\25\1\26\1\43\1\20"+ + "\2\10\1\74\4\10\1\75\5\10\1\30\3\10\1\37\2\10\1\24"+ + "\1\46\1\31\1\107\1\10\1\0\1\52\1\50\1\54\1\63\1\44"+ + "\1\40\1\73\1\66\1\61\1\10\1\53\1\64\1\71\1\57\1\56"+ + "\1\67\1\10\1\51\1\55\1\60\1\62\1\72\1\65\1\36\1\70"+ + "\1\10\1\100\1\106\1\101\1\104\6\0\1\113\41\0\1\47\2\0"+ + "\1\6\12\0\1\6\1\0\1\22\2\0\1\6\5\0\2\6\1\112"+ + "\24\6\1\0\37\6\1\0\u01ca\6\4\0\14\6\16\0\5\6\7\0"+ + "\1\6\1\0\1\6\21\0\160\7\5\6\1\0\2\6\2\0\4\6"+ + "\1\0\1\6\6\0\1\6\1\0\3\6\1\0\1\6\1\0\24\6"+ + "\1\0\123\6\1\0\213\6\1\0\5\7\2\0\246\6\1\0\46\6"+ + "\2\0\1\6\7\0\47\6\11\0\55\7\1\0\1\7\1\0\2\7"+ + "\1\0\2\7\1\0\1\7\10\0\33\6\5\0\3\6\35\0\13\7"+ + "\5\0\53\6\37\7\4\0\2\6\1\7\143\6\1\0\1\6\7\7"+ + "\2\0\6\7\2\6\2\7\1\0\4\7\2\6\12\7\3\6\2\0"+ + "\1\6\20\0\1\6\1\7\36\6\33\7\2\0\131\6\13\7\1\6"+ + "\16\0\12\7\41\6\11\7\2\6\4\0\1\6\5\0\26\6\4\7"+ + "\1\6\11\7\1\6\3\7\1\6\5\7\22\0\31\6\3\7\104\0"+ + "\23\6\61\0\40\7\66\6\3\7\1\6\22\7\1\6\7\7\12\6"+ + "\2\7\2\0\12\7\1\0\20\6\3\7\1\0\10\6\2\0\2\6"+ + "\2\0\26\6\1\0\7\6\1\0\1\6\3\0\4\6\2\0\1\7"+ + "\1\6\7\7\2\0\2\7\2\0\3\7\1\6\10\0\1\7\4\0"+ + "\2\6\1\0\3\6\2\7\2\0\12\7\2\6\17\0\3\7\1\0"+ + "\6\6\4\0\2\6\2\0\26\6\1\0\7\6\1\0\2\6\1\0"+ + "\2\6\1\0\2\6\2\0\1\7\1\0\5\7\4\0\2\7\2\0"+ + "\3\7\3\0\1\7\7\0\4\6\1\0\1\6\7\0\14\7\3\6"+ + "\1\7\13\0\3\7\1\0\11\6\1\0\3\6\1\0\26\6\1\0"+ + "\7\6\1\0\2\6\1\0\5\6\2\0\1\7\1\6\10\7\1\0"+ + "\3\7\1\0\3\7\2\0\1\6\17\0\2\6\2\7\2\0\12\7"+ + "\21\0\3\7\1\0\10\6\2\0\2\6\2\0\26\6\1\0\7\6"+ + "\1\0\2\6\1\0\5\6\2\0\1\7\1\6\7\7\2\0\2\7"+ + "\2\0\3\7\10\0\2\7\4\0\2\6\1\0\3\6\2\7\2\0"+ + "\12\7\1\0\1\6\20\0\1\7\1\6\1\0\6\6\3\0\3\6"+ + "\1\0\4\6\3\0\2\6\1\0\1\6\1\0\2\6\3\0\2\6"+ + "\3\0\3\6\3\0\14\6\4\0\5\7\3\0\3\7\1\0\4\7"+ + "\2\0\1\6\6\0\1\7\16\0\12\7\20\0\4\7\1\0\10\6"+ + "\1\0\3\6\1\0\27\6\1\0\20\6\3\0\1\6\7\7\1\0"+ + "\3\7\1\0\4\7\7\0\2\7\1\0\2\6\6\0\2\6\2\7"+ + "\2\0\12\7\21\0\3\7\1\0\10\6\1\0\3\6\1\0\27\6"+ + "\1\0\12\6\1\0\5\6\2\0\1\7\1\6\7\7\1\0\3\7"+ + "\1\0\4\7\7\0\2\7\7\0\1\6\1\0\2\6\2\7\2\0"+ + "\12\7\1\0\2\6\16\0\3\7\1\0\10\6\1\0\3\6\1\0"+ + "\51\6\2\0\1\6\7\7\1\0\3\7\1\0\4\7\1\6\10\0"+ + "\1\7\10\0\2\6\2\7\2\0\12\7\12\0\6\6\2\0\2\7"+ + "\1\0\22\6\3\0\30\6\1\0\11\6\1\0\1\6\2\0\7\6"+ + "\3\0\1\7\4\0\6\7\1\0\1\7\1\0\10\7\6\0\12\7"+ + "\2\0\2\7\15\0\60\6\1\7\2\6\7\7\5\0\7\6\10\7"+ + "\1\0\12\7\47\0\2\6\1\0\1\6\2\0\2\6\1\0\1\6"+ + "\2\0\1\6\6\0\4\6\1\0\7\6\1\0\3\6\1\0\1\6"+ + "\1\0\1\6\2\0\2\6\1\0\4\6\1\7\2\6\6\7\1\0"+ + "\2\7\1\6\2\0\5\6\1\0\1\6\1\0\6\7\2\0\12\7"+ + "\2\0\4\6\40\0\1\6\27\0\2\7\6\0\12\7\13\0\1\7"+ + "\1\0\1\7\1\0\1\7\4\0\2\7\10\6\1\0\44\6\4\0"+ + "\24\7\1\0\2\7\5\6\13\7\1\0\44\7\11\0\1\7\71\0"+ + "\53\6\24\7\1\6\12\7\6\0\6\6\4\7\4\6\3\7\1\6"+ + "\3\7\2\6\7\7\3\6\4\7\15\6\14\7\1\6\17\7\2\0"+ + "\46\6\1\0\1\6\5\0\1\6\2\0\53\6\1\0\u014d\6\1\0"+ + "\4\6\2\0\7\6\1\0\1\6\1\0\4\6\2\0\51\6\1\0"+ + "\4\6\2\0\41\6\1\0\4\6\2\0\7\6\1\0\1\6\1\0"+ + "\4\6\2\0\17\6\1\0\71\6\1\0\4\6\2\0\103\6\2\0"+ + "\3\7\40\0\20\6\20\0\125\6\14\0\u026c\6\2\0\21\6\1\0"+ + "\32\6\5\0\113\6\3\0\3\7\10\6\7\0\15\6\1\0\4\6"+ + "\3\7\13\0\22\6\3\7\13\0\22\6\2\7\14\0\15\6\1\0"+ + "\3\6\1\0\2\7\14\0\64\6\40\7\3\0\1\6\4\0\1\6"+ + "\1\7\2\0\12\7\41\0\3\7\2\0\12\7\6\0\130\6\10\0"+ + "\51\6\1\7\1\6\5\0\106\6\12\0\37\6\1\0\14\7\4\0"+ + "\14\7\12\0\12\7\36\6\2\0\5\6\13\0\54\6\4\0\21\7"+ + "\7\6\2\7\6\0\12\7\46\0\27\6\5\7\4\0\65\6\12\7"+ + "\1\0\35\7\2\0\13\7\6\0\12\7\15\0\1\6\10\0\16\7"+ + "\102\0\5\7\57\6\21\7\7\6\4\0\12\7\21\0\11\7\14\0"+ + "\3\7\36\6\15\7\2\6\12\7\54\6\16\7\14\0\44\6\24\7"+ + "\10\0\12\7\3\0\3\6\12\7\44\6\122\0\3\7\1\0\25\7"+ + "\4\6\1\7\4\6\3\7\2\6\1\0\2\7\6\0\300\6\66\7"+ + "\6\0\4\7\u0116\6\2\0\6\6\2\0\46\6\2\0\6\6\2\0"+ + "\10\6\1\0\1\6\1\0\1\6\1\0\1\6\1\0\37\6\2\0"+ + "\65\6\1\0\7\6\1\0\1\6\3\0\3\6\1\0\7\6\3\0"+ + "\4\6\2\0\6\6\4\0\15\6\5\0\3\6\1\0\7\6\3\0"+ + "\14\0\2\0\32\0\1\113\1\113\25\0\2\7\23\0\1\7\33\0"+ + "\1\0\1\6\15\0\1\6\20\0\15\6\63\0\15\7\4\0\1\7"+ + "\3\0\14\7\21\0\1\6\4\0\1\6\2\0\12\6\1\0\1\6"+ + "\3\0\5\6\6\0\1\6\1\0\1\6\1\0\1\6\1\0\4\6"+ + "\1\0\13\6\2\0\4\6\5\0\5\6\4\0\1\6\21\0\43\7"+ + "\2\6\4\7\7\0\u0a70\0\57\6\1\0\57\6\1\0\205\6\6\0"+ + "\4\6\3\7\2\6\14\0\46\6\1\0\1\6\5\0\1\6\2\0"+ + "\70\6\7\0\1\6\17\0\1\7\27\6\11\0\7\6\1\0\7\6"+ + "\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6"+ + "\1\0\7\6\1\0\40\7\57\0\1\6\u01c0\0\21\0\4\0\2\6"+ + "\1\7\31\0\17\7\1\0\5\6\2\0\3\7\2\6\4\0\126\6"+ + "\2\0\2\7\2\0\3\6\1\0\132\6\1\0\4\6\5\0\51\6"+ + "\3\0\136\6\21\0\33\6\65\0\20\6\u0200\0\u19b6\6\112\0\u51cd\6"+ + "\63\0\u048d\6\103\0\56\6\2\0\u010d\6\3\0\20\6\12\7\2\6"+ + "\24\0\57\6\1\7\4\0\12\7\1\0\37\6\1\0\1\7\106\6"+ + "\14\7\45\0\11\6\2\0\147\6\2\0\4\6\1\0\36\6\2\0"+ + "\2\6\105\0\13\6\1\7\3\6\1\7\4\6\1\7\27\6\5\7"+ + "\30\0\64\6\14\0\2\7\62\6\21\7\13\0\12\7\6\0\22\7"+ + "\6\6\3\0\1\6\4\0\12\7\34\6\10\7\2\0\27\6\15\7"+ + "\14\0\35\6\3\0\4\7\57\6\16\7\16\0\1\6\12\7\6\0"+ + "\5\6\1\7\12\6\12\7\5\6\1\0\51\6\16\7\11\0\3\6"+ + "\1\7\10\6\2\7\2\0\12\7\6\0\27\6\3\0\1\6\3\7"+ + "\62\6\1\7\1\6\3\7\2\6\2\7\5\6\2\7\1\6\1\7"+ + "\1\6\30\0\3\6\2\0\13\6\5\7\2\0\3\6\2\7\12\0"+ + "\6\6\2\0\6\6\2\0\6\6\11\0\7\6\1\0\7\6\1\0"+ + "\53\6\1\0\4\6\4\0\2\6\132\0\43\6\10\7\1\0\2\7"+ + "\2\0\12\7\6\0\u2ba4\6\14\0\27\6\4\0\61\6\4\0\u1800\0"+ + "\u0900\0\u016e\6\2\0\152\6\46\0\7\6\14\0\5\6\5\0\1\6"+ + "\1\7\12\6\1\0\15\6\1\0\5\6\1\0\1\6\1\0\2\6"+ + "\1\0\2\6\1\0\154\6\41\0\u016b\6\22\0\100\6\2\0\66\6"+ + "\10\0\40\0\14\6\4\0\20\7\20\0\16\7\5\0\2\7\30\0"+ + "\3\7\40\0\5\6\1\0\207\6\23\0\12\7\7\0\32\6\4\0"+ + "\1\7\1\0\32\6\13\0\131\6\3\0\6\6\2\0\6\6\2\0"+ + "\6\6\2\0\3\6\41\0\2\0\14\6\1\0\32\6\1\0\23\6"+ + "\1\0\2\6\1\0\17\6\2\0\16\6\42\0\173\6\105\0\65\7"+ + "\210\0\1\7\202\0\35\6\3\0\61\6\17\0\1\7\37\0\40\6"+ + "\20\0\21\6\1\7\10\6\1\7\5\0\46\6\5\7\5\0\36\6"+ + "\2\0\44\6\4\0\10\6\1\0\5\7\52\0\236\6\2\0\12\7"+ + "\126\0\50\6\10\0\64\6\234\0\u0137\6\11\0\26\6\12\0\10\6"+ + "\230\0\6\6\2\0\1\6\1\0\54\6\1\0\2\6\3\0\1\6"+ + "\2\0\27\6\12\0\27\6\11\0\37\6\141\0\26\6\12\0\32\6"+ + "\106\0\70\6\6\0\2\6\100\0\1\6\3\7\1\0\2\7\5\0"+ + "\4\7\4\6\1\0\3\6\1\0\33\6\4\0\3\7\4\0\1\7"+ + "\40\0\35\6\3\0\35\6\43\0\10\6\1\0\34\6\2\7\31\0"+ + "\66\6\12\0\26\6\12\0\23\6\15\0\22\6\156\0\111\6\u03b7\0"+ + "\3\7\65\6\17\7\37\0\12\7\17\0\4\7\55\6\13\7\25\0"+ + "\31\6\7\0\12\7\6\0\3\7\44\6\16\7\1\0\12\7\20\0"+ + "\43\6\1\7\2\0\1\6\11\0\3\7\60\6\16\7\4\6\13\0"+ + "\12\7\1\6\45\0\22\6\1\0\31\6\14\7\170\0\57\6\14\7"+ + "\5\0\12\7\7\0\3\7\1\0\10\6\2\0\2\6\2\0\26\6"+ + "\1\0\7\6\1\0\2\6\1\0\5\6\2\0\1\7\1\6\7\7"+ + "\2\0\2\7\2\0\3\7\11\0\1\7\5\0\5\6\2\7\2\0"+ + "\7\7\3\0\5\7\u010b\0\60\6\24\7\2\6\1\0\1\6\10\0"+ + "\12\7\246\0\57\6\7\7\2\0\11\7\77\0\60\6\21\7\3\0"+ + "\1\6\13\0\12\7\46\0\53\6\15\7\10\0\12\7\u01d6\0\100\6"+ + "\12\7\25\0\1\6\u01c0\0\71\6\u0507\0\u0399\6\147\0\157\7\u0b91\0"+ + "\u042f\6\u33d1\0\u0239\6\7\0\37\6\1\0\12\7\146\0\36\6\2\0"+ + "\5\7\13\0\60\6\7\7\11\0\4\6\14\0\12\7\11\0\25\6"+ + "\5\0\23\6\u0370\0\105\6\13\0\1\6\56\7\20\0\4\7\15\6"+ + "\u4060\0\2\6\u0bfe\0\153\6\5\0\15\6\3\0\11\6\7\0\12\6"+ + "\3\0\2\7\u14c6\0\5\7\3\0\6\7\10\0\10\7\2\0\7\7"+ + "\36\0\4\7\224\0\3\7\u01bb\0\125\6\1\0\107\6\1\0\2\6"+ + "\2\0\1\6\2\0\2\6\2\0\4\6\1\0\14\6\1\0\1\6"+ + "\1\0\7\6\1\0\101\6\1\0\4\6\2\0\10\6\1\0\7\6"+ + "\1\0\34\6\1\0\4\6\1\0\5\6\1\0\1\6\3\0\7\6"+ + "\1\0\u0154\6\2\0\31\6\1\0\31\6\1\0\37\6\1\0\31\6"+ + "\1\0\37\6\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6"+ + "\1\0\31\6\1\0\10\6\2\0\62\7\u1000\0\305\6\13\0\7\7"+ + "\u0529\0\4\6\1\0\33\6\1\0\2\6\1\0\1\6\2\0\1\6"+ + "\1\0\12\6\1\0\4\6\1\0\1\6\1\0\1\6\6\0\1\6"+ + "\4\0\1\6\1\0\1\6\1\0\1\6\1\0\3\6\1\0\2\6"+ + "\1\0\1\6\2\0\1\6\1\0\1\6\1\0\1\6\1\0\1\6"+ + "\1\0\1\6\1\0\2\6\1\0\1\6\2\0\4\6\1\0\7\6"+ + "\1\0\4\6\1\0\4\6\1\0\1\6\1\0\12\6\1\0\21\6"+ + "\5\0\3\6\1\0\5\6\1\0\21\6\u1144\0\ua6d7\6\51\0\u1035\6"+ + "\13\0\336\6\u3fe2\0\u021e\6\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\u06ed\0"+ + "\360\7\uffff\0\uffff\0\ufe12\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\13\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7"+ + "\1\10\1\11\1\12\1\13\1\14\1\15\1\16\1\17"+ + "\1\20\1\21\1\22\1\23\1\15\2\6\1\24\1\25"+ + "\21\6\1\26\1\27\1\30\1\31\1\32\1\33\1\34"+ + "\1\35\1\36\1\37\1\40\1\41\1\42\2\43\1\44"+ + "\1\1\1\42\2\45\2\46\1\42\2\1\1\47\1\50"+ + "\1\1\1\51\2\1\1\52\1\1\1\53\2\42\2\54"+ + "\2\42\1\55\1\42\1\1\1\56\1\3\1\0\1\57"+ + "\1\60\1\61\1\62\1\63\1\64\1\65\1\66\1\67"+ + "\1\70\1\71\1\72\1\73\1\74\1\75\1\76\1\0"+ + "\1\77\1\63\1\100\1\0\2\100\7\6\1\101\1\102"+ + "\1\0\2\6\1\103\16\6\1\104\1\105\1\106\4\6"+ + "\1\107\13\6\1\110\1\111\1\112\1\113\1\114\1\115"+ + "\1\116\1\117\1\120\1\116\1\121\1\122\1\123\1\124"+ + "\1\125\1\126\1\116\1\127\1\0\1\130\1\0\1\131"+ + "\1\0\1\132\1\133\1\0\1\134\4\0\1\135\2\0"+ + "\1\136\4\137\2\3\2\0\1\140\1\141\1\142\1\143"+ + "\1\144\1\0\1\63\1\145\2\146\1\100\1\6\1\147"+ + "\5\6\1\150\6\6\1\151\4\6\1\152\4\6\1\153"+ + "\6\6\1\154\12\6\1\155\1\6\1\156\1\6\1\157"+ + "\3\0\1\134\1\160\1\161\1\0\1\162\2\0\1\163"+ + "\1\164\1\165\1\0\1\166\1\146\1\100\4\6\1\167"+ + "\1\170\2\6\1\171\12\6\1\172\1\173\1\6\1\174"+ + "\11\6\1\175\5\6\1\176\1\6\1\177\2\0\1\200"+ + "\1\201\1\0\1\146\1\100\1\202\1\203\2\6\1\204"+ + "\1\6\1\205\1\206\1\6\1\207\1\6\1\210\4\6"+ + "\1\211\11\6\1\212\5\6\1\0\1\146\1\100\3\6"+ + "\1\213\1\6\1\214\1\215\1\6\1\216\1\6\1\217"+ + "\3\6\1\220\3\6\1\221\4\6\1\222\1\6\1\0"+ + "\1\146\1\100\1\223\1\6\1\224\10\6\1\225\1\226"+ + "\1\6\1\227\1\230\1\6\1\0\1\146\1\100\1\231"+ + "\1\232\1\233\3\6\1\234\3\6\1\235\1\0\1\146"+ + "\1\100\1\236\1\6\1\237\1\6\1\240\1\241\1\242"+ + "\1\146\1\100\1\243\1\244\6\100"; + + private static int [] zzUnpackAction() { + int [] result = new int[448]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\114\0\230\0\344\0\u0130\0\u017c\0\u01c8\0\u0214"+ + "\0\u0260\0\u02ac\0\u02f8\0\u0344\0\u0390\0\u0344\0\u03dc\0\u0428"+ + "\0\u0474\0\u04c0\0\u050c\0\u0558\0\u05a4\0\u05f0\0\u063c\0\u0688"+ + "\0\u06d4\0\u0344\0\u0344\0\u0344\0\u0720\0\u0344\0\u0344\0\u076c"+ + "\0\u07b8\0\u0804\0\u0850\0\u089c\0\u08e8\0\u0934\0\u0980\0\u09cc"+ + "\0\u0a18\0\u0a64\0\u0ab0\0\u0afc\0\u0b48\0\u0b94\0\u0be0\0\u0c2c"+ + "\0\u0c78\0\u0cc4\0\u0d10\0\u0d5c\0\u0da8\0\u0344\0\u0344\0\u0344"+ + "\0\u0344\0\u0344\0\u0344\0\u0344\0\u0df4\0\u0e40\0\u0e8c\0\u0ed8"+ + "\0\u0344\0\u0f24\0\u0f70\0\u0344\0\u0344\0\u0fbc\0\u1008\0\u1054"+ + "\0\u0344\0\u10a0\0\u0344\0\u10ec\0\u1138\0\u1184\0\u0344\0\u0344"+ + "\0\u11d0\0\u0344\0\u121c\0\u1268\0\u0344\0\u12b4\0\u0344\0\u0344"+ + "\0\u1300\0\u134c\0\u0344\0\u1398\0\u13e4\0\u0344\0\u1430\0\u147c"+ + "\0\u0344\0\u14c8\0\u1514\0\u0344\0\u0344\0\u1560\0\u0344\0\u15ac"+ + "\0\u0344\0\u15f8\0\u1644\0\u0344\0\u0344\0\u1690\0\u0344\0\u0344"+ + "\0\u16dc\0\u0344\0\u0344\0\u1728\0\u1774\0\u17c0\0\u180c\0\u1858"+ + "\0\u18a4\0\u18f0\0\u193c\0\u1988\0\u19d4\0\u1a20\0\u1a6c\0\u1ab8"+ + "\0\u1b04\0\u0344\0\u0344\0\u1b50\0\u1b9c\0\u1be8\0\u04c0\0\u1c34"+ + "\0\u1c80\0\u1ccc\0\u1d18\0\u1d64\0\u1db0\0\u1dfc\0\u1e48\0\u1e94"+ + "\0\u1ee0\0\u1f2c\0\u1f78\0\u1fc4\0\u2010\0\u04c0\0\u04c0\0\u205c"+ + "\0\u20a8\0\u20f4\0\u2140\0\u218c\0\u04c0\0\u21d8\0\u2224\0\u2270"+ + "\0\u22bc\0\u2308\0\u2354\0\u23a0\0\u23ec\0\u2438\0\u2484\0\u24d0"+ + "\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344"+ + "\0\u0344\0\u251c\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344\0\u0344"+ + "\0\u2568\0\u0344\0\u1184\0\u0344\0\u11d0\0\u0344\0\u121c\0\u0344"+ + "\0\u0344\0\u12b4\0\u25b4\0\u2600\0\u264c\0\u2698\0\u26e4\0\u2730"+ + "\0\u277c\0\u27c8\0\u0344\0\u0344\0\u251c\0\u2568\0\u2814\0\u2860"+ + "\0\u0344\0\u28ac\0\u28f8\0\u0344\0\u0344\0\u0344\0\u2944\0\u0344"+ + "\0\u2990\0\u2990\0\u0344\0\u29dc\0\u1858\0\u2a28\0\u2a74\0\u04c0"+ + "\0\u2ac0\0\u2b0c\0\u2b58\0\u2ba4\0\u2bf0\0\u2c3c\0\u2c88\0\u2cd4"+ + "\0\u2d20\0\u2d6c\0\u2db8\0\u2e04\0\u04c0\0\u2e50\0\u2e9c\0\u2ee8"+ + "\0\u2f34\0\u04c0\0\u2f80\0\u2fcc\0\u3018\0\u3064\0\u04c0\0\u30b0"+ + "\0\u30fc\0\u3148\0\u3194\0\u31e0\0\u322c\0\u04c0\0\u3278\0\u32c4"+ + "\0\u3310\0\u335c\0\u33a8\0\u33f4\0\u3440\0\u348c\0\u34d8\0\u3524"+ + "\0\u04c0\0\u3570\0\u04c0\0\u35bc\0\u04c0\0\u3608\0\u3654\0\u25b4"+ + "\0\u0344\0\u0344\0\u0344\0\u36a0\0\u0344\0\u36ec\0\u3738\0\u3784"+ + "\0\u0344\0\u0344\0\u37d0\0\u0344\0\u381c\0\u3868\0\u38b4\0\u3900"+ + "\0\u394c\0\u3998\0\u04c0\0\u04c0\0\u39e4\0\u3a30\0\u04c0\0\u3a7c"+ + "\0\u3ac8\0\u3b14\0\u3b60\0\u3bac\0\u3bf8\0\u3c44\0\u3c90\0\u3cdc"+ + "\0\u3d28\0\u04c0\0\u04c0\0\u3d74\0\u04c0\0\u3dc0\0\u3e0c\0\u3e58"+ + "\0\u3ea4\0\u3ef0\0\u3f3c\0\u3f88\0\u3fd4\0\u4020\0\u04c0\0\u406c"+ + "\0\u40b8\0\u4104\0\u4150\0\u419c\0\u04c0\0\u41e8\0\u0344\0\u251c"+ + "\0\u4234\0\u0344\0\u0344\0\u4280\0\u42cc\0\u4318\0\u04c0\0\u4364"+ + "\0\u43b0\0\u43fc\0\u04c0\0\u4448\0\u04c0\0\u04c0\0\u4494\0\u04c0"+ + "\0\u44e0\0\u04c0\0\u452c\0\u4578\0\u45c4\0\u4610\0\u04c0\0\u465c"+ + "\0\u46a8\0\u46f4\0\u4740\0\u478c\0\u47d8\0\u4824\0\u4870\0\u48bc"+ + "\0\u04c0\0\u4908\0\u4954\0\u49a0\0\u49ec\0\u4a38\0\u4a84\0\u4ad0"+ + "\0\u4b1c\0\u4b68\0\u4bb4\0\u4c00\0\u04c0\0\u4c4c\0\u04c0\0\u04c0"+ + "\0\u4c98\0\u04c0\0\u4ce4\0\u04c0\0\u4d30\0\u4d7c\0\u4dc8\0\u04c0"+ + "\0\u4e14\0\u4e60\0\u4eac\0\u04c0\0\u4ef8\0\u4f44\0\u4f90\0\u4fdc"+ + "\0\u04c0\0\u5028\0\u5074\0\u50c0\0\u510c\0\u04c0\0\u5158\0\u04c0"+ + "\0\u51a4\0\u51f0\0\u523c\0\u5288\0\u52d4\0\u5320\0\u536c\0\u53b8"+ + "\0\u04c0\0\u04c0\0\u5404\0\u04c0\0\u04c0\0\u5450\0\u549c\0\u54e8"+ + "\0\u5534\0\u04c0\0\u04c0\0\u04c0\0\u5580\0\u55cc\0\u5618\0\u04c0"+ + "\0\u5664\0\u56b0\0\u56fc\0\u04c0\0\u5748\0\u5794\0\u57e0\0\u04c0"+ + "\0\u582c\0\u04c0\0\u5878\0\u04c0\0\u04c0\0\u0344\0\u0344\0\u58c4"+ + "\0\u04c0\0\u04c0\0\u5910\0\u595c\0\u59a8\0\u59f4\0\u5a40\0\u17c0"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[448]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\14\1\15\1\16\1\17\1\20\1\21\1\22\1\14"+ + "\1\22\1\23\1\24\1\17\1\25\1\26\1\27\1\30"+ + "\1\22\1\31\1\14\1\32\1\33\4\22\1\34\1\35"+ + "\1\36\1\37\1\40\2\22\1\41\2\31\1\22\1\42"+ + "\1\43\1\14\1\44\1\45\1\46\1\47\1\22\1\50"+ + "\1\51\1\52\1\53\1\54\1\55\1\56\1\57\1\22"+ + "\1\60\1\22\1\61\2\22\1\62\1\63\1\64\1\65"+ + "\1\66\1\67\1\70\1\71\1\72\1\73\1\74\1\75"+ + "\1\76\1\77\1\100\1\101\1\22\1\14\1\102\1\103"+ + "\1\104\30\102\1\105\12\102\1\106\45\102\1\107\1\110"+ + "\1\111\31\107\1\105\11\107\1\106\45\107\1\14\1\112"+ + "\1\113\1\114\1\115\3\14\1\116\2\14\1\114\2\14"+ + "\1\117\2\116\4\14\4\116\5\14\3\116\2\14\2\116"+ + "\3\14\26\116\2\14\1\120\46\14\1\121\44\14\1\122"+ + "\14\14\1\112\1\113\1\114\4\14\1\123\2\14\1\114"+ + "\3\14\2\123\2\14\1\124\1\14\4\123\5\14\3\123"+ + "\2\14\2\123\3\14\26\123\2\14\1\125\46\14\1\126"+ + "\44\14\1\127\13\14\1\130\1\112\1\113\26\130\1\131"+ + "\63\130\1\132\1\133\12\130\1\134\77\130\1\112\1\113"+ + "\7\130\1\135\65\130\1\136\13\130\1\137\1\110\1\111"+ + "\43\137\1\140\1\141\44\137\116\0\1\16\114\0\1\17"+ + "\7\0\1\17\104\0\1\142\1\143\24\0\1\144\113\0"+ + "\1\145\67\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\26\22\14\0\1\22\12\0\1\146\1\147"+ + "\6\0\1\150\13\0\1\150\3\0\2\150\33\0\1\151"+ + "\25\0\1\152\1\0\1\153\4\0\2\152\4\0\4\152"+ + "\1\0\1\154\3\0\3\152\2\0\2\152\3\0\26\152"+ + "\2\0\1\155\45\0\1\156\76\0\1\157\14\0\1\160"+ + "\77\0\1\161\13\0\1\162\100\0\1\163\105\0\1\150"+ + "\7\0\1\31\13\0\1\31\3\0\2\31\2\164\101\0"+ + "\1\165\72\0\1\150\7\0\1\166\13\0\1\167\2\170"+ + "\1\0\1\171\1\172\2\164\55\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\173\3\22"+ + "\1\174\2\22\1\175\1\176\13\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\1\22\1\177"+ + "\6\22\3\0\2\22\1\200\11\22\1\201\11\22\14\0"+ + "\1\22\33\0\1\202\12\0\1\203\115\0\1\204\52\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\1\22\1\205\24\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\7\22\1\206\3\0\26\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\5\22\1\207\20\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\2\22\1\210\3\22\1\211\5\22\1\212\11\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\213\3\0\10\22\1\214\1\22\1\215"+ + "\2\22\1\216\10\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\22\22\1\217"+ + "\3\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\220\3\0\2\22\1\221\7\22"+ + "\1\222\13\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\1\22\1\223\14\22"+ + "\1\224\1\22\1\225\5\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\3\22\1\226\4\22"+ + "\3\0\5\22\1\227\1\22\1\230\11\22\1\231\4\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\5\22\1\232\1\22\1\233\16\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\234\3\0\6\22\1\235\11\22\1\236"+ + "\5\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\11\22\1\237\4\22\1\240"+ + "\7\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\1\22\1\241\1\242\7\22"+ + "\1\243\13\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\244\3\22"+ + "\1\245\17\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\246\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\7\22\1\247\16\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\2\22\1\250\23\22\14\0\1\22\33\0\1\251\52\0"+ + "\1\252\40\0\1\253\53\0\1\254\37\0\1\255\113\0"+ + "\1\256\61\0\1\102\2\0\30\102\1\0\12\102\1\0"+ + "\45\102\2\0\1\104\111\0\1\257\3\0\27\257\1\260"+ + "\1\261\1\257\1\262\1\257\1\263\5\257\1\264\1\257"+ + "\1\265\1\266\5\257\1\267\1\270\1\257\1\271\30\257"+ + "\1\0\1\107\2\0\31\107\1\0\11\107\1\0\45\107"+ + "\2\0\1\111\113\0\1\113\114\0\1\114\7\0\1\114"+ + "\116\0\1\272\105\0\2\273\3\0\1\273\1\0\4\273"+ + "\2\0\4\273\1\0\1\274\2\0\10\273\3\0\26\273"+ + "\16\0\1\275\2\0\30\275\1\276\60\275\10\0\2\277"+ + "\3\0\1\277\1\0\4\277\2\0\4\277\1\0\1\300"+ + "\2\0\10\277\3\0\26\277\34\0\1\301\75\0\1\302"+ + "\2\0\30\302\1\303\1\304\57\302\31\0\1\305\64\0"+ + "\1\133\126\0\1\306\102\0\1\307\3\0\1\310\3\0"+ + "\1\311\2\0\2\310\2\0\1\312\1\0\4\310\5\0"+ + "\3\310\2\0\2\310\3\0\26\310\2\0\1\313\13\0"+ + "\1\137\2\0\43\137\2\0\44\137\1\314\3\0\32\314"+ + "\1\315\1\314\1\263\5\314\1\264\1\314\1\265\1\266"+ + "\5\314\1\267\1\270\1\314\1\316\27\314\1\317\1\0"+ + "\1\142\1\320\1\321\111\142\5\322\1\323\106\322\11\0"+ + "\1\324\123\0\1\150\13\0\1\150\3\0\2\150\2\164"+ + "\57\0\2\152\3\0\1\152\1\0\4\152\2\0\4\152"+ + "\4\0\10\152\3\0\26\152\50\0\1\325\113\0\1\326"+ + "\77\0\1\327\13\0\1\330\76\0\1\331\3\0\1\332"+ + "\13\0\1\332\3\0\2\332\2\0\1\331\100\0\1\333"+ + "\72\0\1\150\7\0\1\166\13\0\1\166\3\0\2\166"+ + "\2\164\60\0\1\150\7\0\1\166\13\0\1\167\3\0"+ + "\1\171\1\172\2\164\67\0\2\334\3\0\3\334\5\0"+ + "\1\335\2\0\5\334\3\0\1\334\1\0\1\334\1\0"+ + "\1\334\6\0\1\334\41\0\1\150\7\0\1\166\13\0"+ + "\1\172\3\0\2\172\2\164\60\0\1\150\7\0\1\166"+ + "\13\0\1\336\3\0\2\336\2\164\55\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\14\22\1\337"+ + "\11\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\1\22\1\340\24\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\7\22\1\341\16\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\7\22\1\342\16\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\343"+ + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\4\22\1\344\21\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\5\22\1\345\20\22\14\0\1\22\7\0"+ + "\1\346\1\0\1\346\7\0\1\346\4\0\4\346\5\0"+ + "\3\346\2\0\2\346\3\0\26\346\14\0\1\346\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\347"+ + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\10\22\1\350\15\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\5\22\1\351\2\22\1\352\15\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\7\22\1\353\16\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\2\22\1\354\23\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\355\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\356\23\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\17\22\1\357\6\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\11\22\1\360\14\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\7\22\1\361\3\0"+ + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\15\22\1\362\10\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\10\22\1\363\10\22\1\364\4\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\14\22\1\365\11\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\12\22\1\366\5\22\1\367\5\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\1\22\1\370\7\22\1\371\14\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\17\22\1\372\6\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\5\22\1\373"+ + "\2\22\1\374\15\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\17\22\1\375"+ + "\6\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\376\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\13\22\1\377\12\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\3\22\1\u0100\4\22"+ + "\3\0\14\22\1\u0101\11\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\7\22"+ + "\1\u0102\16\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\10\22\1\u0103\15\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\11\22\1\u0104\14\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\6\22\1\u0105\2\22\1\u0106\14\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\4\22\1\u0107\21\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\1\u0108"+ + "\25\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\1\22\1\u0109\24\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\11\22\1\u010a\14\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\10\22\1\u010b\15\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\3\22\1\u010c\4\22\3\0"+ + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\25\22\1\u010d\14\0\1\22"+ + "\21\0\2\u010e\3\0\3\u010e\5\0\1\u010e\2\0\5\u010e"+ + "\3\0\1\u010e\1\0\1\u010e\1\0\1\u010e\6\0\1\u010e"+ + "\50\0\2\u010f\3\0\3\u010f\5\0\1\u010f\2\0\5\u010f"+ + "\3\0\1\u010f\1\0\1\u010f\1\0\1\u010f\6\0\1\u010f"+ + "\30\0\1\u0110\2\0\30\u0110\1\303\1\0\57\u0110\1\304"+ + "\2\0\30\304\1\u0111\60\304\16\0\1\u0112\113\0\1\u0113"+ + "\105\0\1\u0114\6\0\2\u0114\4\0\4\u0114\5\0\3\u0114"+ + "\2\0\2\u0114\3\0\26\u0114\2\0\1\u0115\23\0\2\310"+ + "\3\0\1\310\1\0\4\310\2\0\4\310\4\0\10\310"+ + "\3\0\26\310\33\0\1\u0116\6\0\1\u0117\77\0\1\u0118"+ + "\6\0\2\u0118\4\0\4\u0118\5\0\3\u0118\2\0\2\u0118"+ + "\3\0\26\u0118\2\0\1\u0119\62\0\1\u011a\46\0\1\321"+ + "\111\0\5\322\1\u011b\106\322\4\0\1\321\1\323\140\0"+ + "\1\u011c\102\0\1\332\13\0\1\332\3\0\2\332\71\0"+ + "\2\u011d\3\0\3\u011d\5\0\1\u011d\2\0\5\u011d\3\0"+ + "\1\u011d\1\0\1\u011d\1\0\1\u011d\6\0\1\u011d\41\0"+ + "\1\150\7\0\1\166\13\0\1\u011e\3\0\2\u011e\2\164"+ + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\5\22\1\u011f\20\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22"+ + "\1\u0120\23\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\4\22\1\u0121\21\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\u0122\3\0\26\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\16\22\1\u0123\7\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\7\22\1\u0124\3\0\26\22"+ + "\14\0\1\22\7\0\3\346\7\0\2\346\3\0\4\346"+ + "\4\0\10\346\3\0\26\346\14\0\1\346\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22"+ + "\1\u0125\23\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\12\22\1\u0126\13\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\u0127\3\0\26\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\4\22\1\u0128\21\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\5\22\1\u0129"+ + "\2\22\1\u012a\15\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\5\22\1\u012b"+ + "\20\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\10\22\1\u012c\15\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\7\22\1\u012d\3\0\26\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\u012e\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\1\22\1\u012f\24\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\11\22\1\u0130\14\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22"+ + "\1\u0131\3\0\26\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\14\22\1\u0132"+ + "\11\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\u0133\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\6\22\1\u0134\17\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\5\22"+ + "\1\u0135\20\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u0136\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\10\22\1\u0137\15\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u0138"+ + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\6\22\1\u0139\5\22"+ + "\1\u013a\11\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u013b\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\2\22\1\u013c\23\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u013d"+ + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u013e\23\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\16\22\1\u013f\7\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\14\22\1\u0140\11\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\u0141\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\22\22\1\u0142\3\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\3\22\1\u0143\22\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\14\22\1\u0144\11\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\13\22"+ + "\1\u0145\12\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\11\22\1\u0146\14\22"+ + "\14\0\1\22\21\0\2\u0147\3\0\3\u0147\5\0\1\u0147"+ + "\2\0\5\u0147\3\0\1\u0147\1\0\1\u0147\1\0\1\u0147"+ + "\6\0\1\u0147\50\0\2\u0148\3\0\3\u0148\5\0\1\u0148"+ + "\2\0\5\u0148\3\0\1\u0148\1\0\1\u0148\1\0\1\u0148"+ + "\6\0\1\u0148\31\0\2\u0149\5\0\2\u0114\1\0\1\u0149"+ + "\1\0\1\u0114\1\u014a\4\u0114\2\0\4\u0114\4\0\10\u0114"+ + "\3\0\26\u0114\33\0\1\u014b\123\0\1\u014c\76\0\2\u0118"+ + "\3\0\1\u0118\1\0\4\u0118\2\0\4\u0118\4\0\10\u0118"+ + "\3\0\26\u0118\16\0\4\322\1\321\1\u011b\106\322\20\0"+ + "\2\u014d\3\0\3\u014d\5\0\1\u014d\2\0\5\u014d\3\0"+ + "\1\u014d\1\0\1\u014d\1\0\1\u014d\6\0\1\u014d\41\0"+ + "\1\150\7\0\1\166\13\0\1\u014e\3\0\2\u014e\2\164"+ + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22"+ + "\1\u014f\3\0\26\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\14\22\1\u0150"+ + "\11\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\10\22\1\u0151\15\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\7\22\1\u0152\16\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\3\22\1\u0153\22\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\1\22\1\u0154"+ + "\24\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\16\22\1\u0155\7\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\10\22\1\u0156\15\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\11\22\1\u0157\14\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\5\22\1\u0158"+ + "\20\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\11\22\1\u0159\14\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\1\22\1\u015a\24\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\4\22\1\u015b\21\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\1\22\1\u015c"+ + "\24\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\22\22\1\u015d\3\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\5\22\1\u015e\20\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\15\22\1\u015f\10\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\6\22\1\u0160"+ + "\17\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\2\22\1\u0161\23\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\1\22\1\u0162\24\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\1\22\1\u0163\24\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\7\22\1\u0164\3\0\26\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\3\22\1\u0165\4\22\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\12\22\1\u0166\13\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\u0167\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\21\22\1\u0168\4\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\7\22\1\u0169\3\0\26\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\7\22\1\u016a"+ + "\3\0\26\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\2\22\1\u016b\23\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\2\22\1\u016c\23\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\11\22\1\u016d\14\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\7\22"+ + "\1\u016e\16\22\14\0\1\22\2\0\2\u0149\10\0\1\u0149"+ + "\2\0\1\u014a\123\0\1\u016f\105\0\2\u0170\3\0\3\u0170"+ + "\5\0\1\u0170\2\0\5\u0170\3\0\1\u0170\1\0\1\u0170"+ + "\1\0\1\u0170\6\0\1\u0170\41\0\1\150\7\0\1\166"+ + "\13\0\1\u0171\3\0\2\u0171\2\164\55\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\14\22\1\u0172"+ + "\11\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\11\22\1\u0173\14\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\13\22\1\u0174\12\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\7\22\1\u0175\16\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\7\22\1\u0176"+ + "\16\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\4\22\1\u0177\21\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\16\22\1\u0178\7\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\11\22\1\u0179\14\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\7\22\1\u017a\3\0\26\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\17\22\1\u017b\6\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\3\22"+ + "\1\u017c\4\22\3\0\26\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\7\22"+ + "\1\u017d\16\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\3\22\1\u017e\4\22\3\0\7\22"+ + "\1\u017f\16\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\10\22\1\u0180\15\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\21\22\1\u0181\4\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\11\22\1\u0182\14\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\14\22"+ + "\1\u0183\11\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u0184\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\11\22\1\u0185\14\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\4\22\1\u0186\21\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u0187"+ + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\23\22\1\u0188\2\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\4\22\1\u0189\21\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\11\22\1\u018a\14\22\14\0\1\22\30\0\1\u018b\104\0"+ + "\2\u018c\3\0\3\u018c\5\0\1\u018c\2\0\5\u018c\3\0"+ + "\1\u018c\1\0\1\u018c\1\0\1\u018c\6\0\1\u018c\41\0"+ + "\1\150\7\0\1\166\13\0\1\u018d\3\0\2\u018d\2\164"+ + "\55\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\20\22\1\u018e\5\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\6\22"+ + "\1\u018f\17\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\5\22\1\u0190\20\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\12\22\1\u0191\13\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\13\22\1\u0192\12\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\2\22"+ + "\1\u0193\23\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\4\22\1\u0194\21\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\2\22\1\u0195\23\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\10\22"+ + "\3\0\2\22\1\u0196\23\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u0197\3\0"+ + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\7\22\1\u0198\16\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\10\22\1\u0199\15\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\4\22\1\u019a\21\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u019b"+ + "\15\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\u019c\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22"+ + "\1\u019d\3\0\26\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\10\22\1\u019e"+ + "\15\22\14\0\1\22\31\0\1\u019f\103\0\2\u01a0\3\0"+ + "\3\u01a0\5\0\1\u01a0\2\0\5\u01a0\3\0\1\u01a0\1\0"+ + "\1\u01a0\1\0\1\u01a0\6\0\1\u01a0\41\0\1\150\7\0"+ + "\1\166\13\0\1\u01a1\3\0\2\u01a1\2\164\55\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\7\22"+ + "\1\u01a2\16\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u01a3\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\7\22\1\u01a4\3\0\26\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\4\22"+ + "\1\u01a5\21\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\7\22\1\u01a6\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\4\22\1\u01a7\21\22\14\0\1\22\7\0"+ + "\3\22\7\0\2\22\3\0\4\22\4\0\10\22\3\0"+ + "\14\22\1\u01a8\11\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\7\22\1\u01a9"+ + "\16\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\7\22\1\u01aa\3\0\26\22\14\0\1\22"+ + "\7\0\3\22\7\0\2\22\3\0\4\22\4\0\7\22"+ + "\1\u01ab\3\0\26\22\14\0\1\22\7\0\3\22\7\0"+ + "\2\22\3\0\4\22\4\0\10\22\3\0\20\22\1\u01ac"+ + "\5\22\14\0\1\22\30\0\1\u01ad\104\0\2\u01ae\3\0"+ + "\3\u01ae\5\0\1\u01ae\2\0\5\u01ae\3\0\1\u01ae\1\0"+ + "\1\u01ae\1\0\1\u01ae\6\0\1\u01ae\41\0\1\150\7\0"+ + "\1\166\13\0\1\u01af\3\0\2\u01af\2\164\55\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\7\22\1\u01b0\3\0"+ + "\26\22\14\0\1\22\7\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\10\22\3\0\6\22\1\u01b1\17\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\7\22\1\u01b2\3\0\26\22\14\0\1\22\7\0\3\22"+ + "\7\0\2\22\3\0\4\22\4\0\10\22\3\0\10\22"+ + "\1\u01b3\15\22\14\0\1\22\7\0\3\22\7\0\2\22"+ + "\3\0\4\22\4\0\10\22\3\0\13\22\1\u01b4\12\22"+ + "\14\0\1\22\7\0\3\22\7\0\2\22\3\0\4\22"+ + "\4\0\10\22\3\0\13\22\1\u01b5\12\22\14\0\1\22"+ + "\25\0\1\u01b6\107\0\2\u01b7\3\0\3\u01b7\5\0\1\u01b7"+ + "\2\0\5\u01b7\3\0\1\u01b7\1\0\1\u01b7\1\0\1\u01b7"+ + "\6\0\1\u01b7\41\0\1\150\7\0\1\166\13\0\1\u01b8"+ + "\3\0\2\u01b8\2\164\55\0\3\22\7\0\2\22\3\0"+ + "\4\22\4\0\3\22\1\u01b9\4\22\3\0\26\22\14\0"+ + "\1\22\7\0\3\22\7\0\2\22\3\0\4\22\4\0"+ + "\10\22\3\0\5\22\1\u01ba\20\22\14\0\1\22\12\0"+ + "\1\150\7\0\1\166\13\0\1\u01bb\3\0\2\u01bb\2\164"+ + "\60\0\1\150\7\0\1\166\13\0\1\u01bc\3\0\2\u01bc"+ + "\2\164\60\0\1\150\7\0\1\166\13\0\1\u01bd\3\0"+ + "\2\u01bd\2\164\60\0\1\150\7\0\1\166\13\0\1\u01be"+ + "\3\0\2\u01be\2\164\60\0\1\150\7\0\1\166\13\0"+ + "\1\u01bf\3\0\2\u01bf\2\164\60\0\1\150\7\0\1\166"+ + "\13\0\1\u01c0\3\0\2\u01c0\2\164\47\0"; + + private static int [] zzUnpackTrans() { + int [] result = new int[23180]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\13\0\1\11\1\1\1\11\13\1\3\11\1\1\2\11"+ + "\26\1\7\11\4\1\1\11\2\1\2\11\3\1\1\11"+ + "\1\1\1\11\3\1\2\11\1\1\1\11\2\1\1\11"+ + "\1\1\2\11\2\1\1\11\2\1\1\11\2\1\1\11"+ + "\1\1\1\0\2\11\1\1\1\11\1\1\1\11\2\1"+ + "\2\11\1\1\2\11\1\1\2\11\1\0\3\1\1\0"+ + "\11\1\2\11\1\0\44\1\11\11\1\1\6\11\1\1"+ + "\1\11\1\0\1\11\1\0\1\11\1\0\2\11\1\0"+ + "\1\1\4\0\1\1\2\0\2\11\4\1\1\11\2\0"+ + "\3\11\1\1\1\11\1\0\1\1\1\11\62\1\3\0"+ + "\3\11\1\0\1\11\2\0\1\1\2\11\1\0\1\11"+ + "\52\1\1\11\2\0\2\11\1\0\42\1\1\0\33\1"+ + "\1\0\23\1\1\0\15\1\1\0\10\1\2\11\11\1"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[448]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /** + * The number of occupied positions in zzBuffer beyond zzEndRead. + * When a lead/high surrogate has been read from the input stream + * into the final zzBuffer position, this will have a value of 1; + * otherwise, it will have a value of 0. + */ + private int zzFinalHighSurrogate = 0; + + /* user code: */ + + private String sourceCode; + + public ActionScriptLexer(String sourceCode){ + this(new StringReader(sourceCode)); + this.sourceCode = sourceCode; + } + + public void yypushbackstr(String s, int state) + { + sourceCode = s + sourceCode.substring(yychar + yylength()); + yyreset(new StringReader(sourceCode)); + yybegin(state); + } + + public void yypushbackstr(String s) + { + yypushbackstr(s, YYINITIAL); + } + + StringBuffer string = new StringBuffer(); + + private static String xmlTagName = ""; + + public int yychar() { + return yychar; + } + + private Stack pushedBack = new Stack<>(); + + public int yyline() { + return yyline + 1; + } + + private List listeners=new ArrayList<>(); + + public void addListener(LexListener listener){ + listeners.add(listener); + } + + public void removeListener(LexListener listener){ + listeners.remove(listener); + } + + public void informListenersLex(ParsedSymbol s){ + for(LexListener l:listeners){ + l.onLex(s); + } + } + + public void informListenersPushBack(ParsedSymbol s){ + for(LexListener l:listeners){ + l.onPushBack(s); + } + } + + public void pushback(ParsedSymbol symb) { + pushedBack.push(symb); + last = null; + informListenersPushBack(symb); + } + + ParsedSymbol last; + public ParsedSymbol lex() throws java.io.IOException, AVM2ParseException{ + ParsedSymbol ret = null; + if (!pushedBack.isEmpty()){ + ret = last = pushedBack.pop(); + } else { + ret = last = yylex(); + } + informListenersLex(ret); + return ret; + } + + + + /** + * Creates a new scanner + * + * @param in the java.io.Reader to read input from. + */ + public ActionScriptLexer(java.io.Reader in) { + this.zzReader = in; + } + + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x110000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 3140) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { + /* if not: blow it up */ + char newBuffer[] = new char[zzBuffer.length*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + } + + /* fill the buffer with new input */ + int requested = zzBuffer.length - zzEndRead; + int totalRead = 0; + while (totalRead < requested) { + int numRead = zzReader.read(zzBuffer, zzEndRead + totalRead, requested - totalRead); + if (numRead == -1) { + break; + } + totalRead += numRead; + } + + if (totalRead > 0) { + zzEndRead += totalRead; + if (totalRead == requested) { /* possibly more input available */ + if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { + --zzEndRead; + zzFinalHighSurrogate = 1; + } + } + return false; + } + + // totalRead = 0: End of stream + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * Internal scan buffer is resized down to its initial length, if it has grown. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + zzFinalHighSurrogate = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + if (zzBuffer.length > ZZ_BUFFERSIZE) + zzBuffer = new char[ZZ_BUFFERSIZE]; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public ParsedSymbol yylex() throws java.io.IOException, AVM2ParseException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar+= zzMarkedPosL-zzStartRead; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + // set up zzAction for empty match case: + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + } + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); + } + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 1: + { + } + case 165: break; + case 2: + { yyline++; + } + case 166: break; + case 3: + { /*ignore*/ + } + case 167: break; + case 4: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); + } + case 168: break; + case 5: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); + } + case 169: break; + case 6: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); + } + case 170: break; + case 7: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); + } + case 171: break; + case 8: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); + } + case 172: break; + case 9: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); + } + case 173: break; + case 10: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); + } + case 174: break; + case 11: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); + } + case 175: break; + case 12: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); + } + case 176: break; + case 13: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); + } + case 177: break; + case 14: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); + } + case 178: break; + case 15: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); + } + case 179: break; + case 16: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); + } + case 180: break; + case 17: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); + } + case 181: break; + case 18: + { string.setLength(0); + yybegin(STRING); + } + case 182: break; + case 19: + { string.setLength(0); + yybegin(CHARLITERAL); + } + case 183: break; + case 20: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); + } + case 184: break; + case 21: + { string.setLength(0); + yybegin(OIDENTIFIER); + } + case 185: break; + case 22: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); + } + case 186: break; + case 23: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); + } + case 187: break; + case 24: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); + } + case 188: break; + case 25: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); + } + case 189: break; + case 26: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); + } + case 190: break; + case 27: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); + } + case 191: break; + case 28: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); + } + case 192: break; + case 29: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); + } + case 193: break; + case 30: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); + } + case 194: break; + case 31: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); + } + case 195: break; + case 32: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); + } + case 196: break; + case 33: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); + } + case 197: break; + case 34: + { string.append(yytext()); + } + case 198: break; + case 35: + { yybegin(YYINITIAL); yyline++; + } + case 199: break; + case 36: + { yybegin(YYINITIAL); + // length also includes the trailing quote + return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); + } + case 200: break; + case 37: + { yybegin(YYINITIAL); yyline++; + } + case 201: break; + case 38: + { string.append(yytext()); yyline++; + } + case 202: break; + case 39: + { yybegin(XML); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_END, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 203: break; + case 40: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRNAMEVAR_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 204: break; + case 41: + { yybegin(YYINITIAL); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRVALVAR_BEGIN, yytext()); + } + case 205: break; + case 42: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRNAMEVAR_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 206: break; + case 43: + { yybegin(YYINITIAL); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRATTRVALVAR_BEGIN, yytext()); + } + case 207: break; + case 44: + { string.append(yytext()); yyline++; + } + case 208: break; + case 45: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_VAR_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 209: break; + case 46: + { yybegin(YYINITIAL); + // length also includes the trailing quote + return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); + } + case 210: break; + case 47: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); + } + case 211: break; + case 48: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); + } + case 212: break; + case 49: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DESCENDANTS, yytext()); + } + case 213: break; + case 50: + { return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, yytext()); + } + case 214: break; + case 51: + { return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); + } + case 215: break; + case 52: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FILTER, yytext()); + } + case 216: break; + case 53: + { yybegin(XMLOPENTAG); + string.setLength(0); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext()); + } + case 217: break; + case 54: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); + } + case 218: break; + case 55: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); + } + case 219: break; + case 56: + { return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext()); + } + case 220: break; + case 57: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); + } + case 221: break; + case 58: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); + } + case 222: break; + case 59: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); + } + case 223: break; + case 60: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); + } + case 224: break; + case 61: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); + } + case 225: break; + case 62: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); + } + case 226: break; + case 63: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); + } + case 227: break; + case 64: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); + } + case 228: break; + case 65: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); + } + case 229: break; + case 66: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); + } + case 230: break; + case 67: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); + } + case 231: break; + case 68: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IF, yytext()); + } + case 232: break; + case 69: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); + } + case 233: break; + case 70: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IN, yytext()); + } + case 234: break; + case 71: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DO, yytext()); + } + case 235: break; + case 72: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); + } + case 236: break; + case 73: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); + } + case 237: break; + case 74: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); + } + case 238: break; + case 75: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); + } + case 239: break; + case 76: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); + } + case 240: break; + case 77: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); + } + case 241: break; + case 78: + { /* ignore illegal character escape */ + } + case 242: break; + case 79: + { string.append('\"'); + } + case 243: break; + case 80: + { string.append('\''); + } + case 244: break; + case 81: + { string.append('\f'); + } + case 245: break; + case 82: + { string.append('\\'); + } + case 246: break; + case 83: + { string.append('\b'); + } + case 247: break; + case 84: + { string.append('\r'); + } + case 248: break; + case 85: + { string.append('\n'); + } + case 249: break; + case 86: + { string.append('\t'); + } + case 250: break; + case 87: + { yybegin(XML); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTFINISHTAG_END, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 251: break; + case 88: + { yybegin(XMLOPENTAGATTRIB); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTENAME, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 252: break; + case 89: + { yybegin(XMLOPENTAG); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); + } + case 253: break; + case 90: + { yybegin(XMLINSTRATTRIB); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTENAME, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 254: break; + case 91: + { yybegin(XML); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTR_END, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 255: break; + case 92: + { yybegin(XMLINSTROPENTAG); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_ATTRIBUTEVALUE, yytext()); + } + case 256: break; + case 93: + { yybegin(XMLOPENTAG); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTTAG_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 257: break; + case 94: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_STARTVARTAG_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 258: break; + case 95: + { throw new AVM2ParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); + } + case 259: break; + case 96: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); + } + case 260: break; + case 97: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); + } + case 261: break; + case 98: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); + } + case 262: break; + case 99: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); + } + case 263: break; + case 100: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); + } + case 264: break; + case 101: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); + } + case 265: break; + case 102: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); + } + case 266: break; + case 103: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FOR, yytext()); + } + case 267: break; + case 104: + { return new ParsedSymbol(SymbolGroup.PREPROCESSOR, SymbolType.PREPROCESSOR, yytext().substring(2)); + } + case 268: break; + case 105: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.SET, yytext()); + } + case 269: break; + case 106: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); + } + case 270: break; + case 107: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRY, yytext()); + } + case 271: break; + case 108: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.USE, yytext()); + } + case 272: break; + case 109: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.VAR, yytext()); + } + case 273: break; + case 110: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.GET, yytext()); + } + case 274: break; + case 111: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); + } + case 275: break; + case 112: + { string.append(yytext()); + yybegin(XML); + String ret = string.toString(); + string.setLength(0); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_CDATA, ret); + } + case 276: break; + case 113: + { string.append(yytext()); + yybegin(XML); + String ret = string.toString(); + string.setLength(0); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_COMMENT, ret); + } + case 277: break; + case 114: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHVARTAG_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 278: break; + case 115: + { yybegin(XMLINSTROPENTAG); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTR_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 279: break; + case 116: + { yybegin(YYINITIAL); + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_INSTRVARTAG_BEGIN, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 280: break; + case 117: + { string.append('\u00A7'); + } + case 281: break; + case 118: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); + } + case 282: break; + case 119: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.EACH, yytext()); + } + case 283: break; + case 120: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.ELSE, yytext()); + } + case 284: break; + case 121: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CASE, yytext()); + } + case 285: break; + case 122: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); + } + case 286: break; + case 123: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); + } + case 287: break; + case 124: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); + } + case 288: break; + case 125: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WITH, yytext()); + } + case 289: break; + case 126: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); + } + case 290: break; + case 127: + { char val = (char) Integer.parseInt(yytext().substring(2), 16); + string.append(val); + } + case 291: break; + case 128: + { pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_FINISHTAG, yytext())); + if (string.length() > 0){ + pushback(new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, string.toString())); + string.setLength(0); + } + return lex(); + } + case 292: break; + case 129: + { String ret = string.toString(); string.setLength(0); string.append(yytext()); yybegin(XMLCOMMENT); + if (!ret.isEmpty()) return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, ret); + } + case 293: break; + case 130: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); + } + case 294: break; + case 131: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.FINAL, yytext()); + } + case 295: break; + case 132: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.BREAK, yytext()); + } + case 296: break; + case 133: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CATCH, yytext()); + } + case 297: break; + case 134: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONST, yytext()); + } + case 298: break; + case 135: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CLASS, yytext()); + } + case 299: break; + case 136: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SUPER, yytext()); + } + case 300: break; + case 137: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THROW, yytext()); + } + case 301: break; + case 138: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WHILE, yytext()); + } + case 302: break; + case 139: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.RETURN, yytext()); + } + case 303: break; + case 140: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.STATIC, yytext()); + } + case 304: break; + case 141: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SWITCH, yytext()); + } + case 305: break; + case 142: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.NATIVE, yytext()); + } + case 306: break; + case 143: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); + } + case 307: break; + case 144: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPORT, yytext()); + } + case 308: break; + case 145: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); + } + case 309: break; + case 146: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PUBLIC, yytext()); + } + case 310: break; + case 147: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FINALLY, yytext()); + } + case 311: break; + case 148: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EXTENDS, yytext()); + } + case 312: break; + case 149: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DEFAULT, yytext()); + } + case 313: break; + case 150: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.DYNAMIC, yytext()); + } + case 314: break; + case 151: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PRIVATE, yytext()); + } + case 315: break; + case 152: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PACKAGE, yytext()); + } + case 316: break; + case 153: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FUNCTION, yytext()); + } + case 317: break; + case 154: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONTINUE, yytext()); + } + case 318: break; + case 155: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.OVERRIDE, yytext()); + } + case 319: break; + case 156: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERNAL, yytext()); + } + case 320: break; + case 157: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); + } + case 321: break; + case 158: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE, yytext()); + } + case 322: break; + case 159: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERFACE, yytext()); + } + case 323: break; + case 160: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); + } + case 324: break; + case 161: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PROTECTED, yytext()); + } + case 325: break; + case 162: + { String ret = string.toString(); string.setLength(0); string.append(yytext() ); yybegin(XMLCDATA); + if (!ret.isEmpty()) return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML_TEXT, ret); + } + case 326: break; + case 163: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); + } + case 327: break; + case 164: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPLEMENTS, yytext()); + } + case 328: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { + return new ParsedSymbol(SymbolGroup.EOF, SymbolType.EOF, null); + } + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolGroup.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolGroup.java index e2342d094..7c5cc7b27 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolGroup.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolGroup.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; /** @@ -32,5 +33,6 @@ public enum SymbolGroup { TYPENAME, EOF, //GLOBALFUNC, - GLOBALCONST + GLOBALCONST, + PREPROCESSOR } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java index 4b06b8220..066fcbf48 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java @@ -1,242 +1,243 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.parser.script; - -import com.jpexs.decompiler.graph.GraphTargetItem; - -/** - * - * @author JPEXS - */ -public enum SymbolType { - //Keywords - - BREAK, - CASE, - CONTINUE, - DEFAULT, - DO, - WHILE, - ELSE, - FOR, - EACH, - IN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IF, - RETURN, - SUPER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SWITCH, - THROW, - TRY, - CATCH, - FINALLY, - WITH, - DYNAMIC, - INTERNAL, - OVERRIDE, - PRIVATE, - PROTECTED, - PUBLIC, - STATIC, - CLASS, - CONST, - EXTENDS, - FUNCTION(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GET, - IMPLEMENTS, - INTERFACE, - NAMESPACE, - PACKAGE, - SET, - VAR, - IMPORT, - USE, - FALSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NULL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - THIS(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TRUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //Operators - PARENT_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PARENT_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SEMICOLON, - COMMA(GraphTargetItem.PRECEDENCE_COMMA, false), - REST, - DOT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - ASSIGN(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - GREATER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - LOWER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT(GraphTargetItem.PRECEDENCE_UNARY, false), - NEGATE(GraphTargetItem.PRECEDENCE_UNARY, false), - TERNAR(GraphTargetItem.PRECEDENCE_CONDITIONAL, true, true), /*!! ternar !!!*/ - COLON(GraphTargetItem.PRECEDENCE_CONDITIONAL, false),/*!! ternar !!!*/ - EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - LOWER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - GREATER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - AND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), - OR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), - INCREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false),//OR Unary - DECREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false), //OR Unary - PLUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), - MINUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), //OR Unary - MULTIPLY(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - DIVIDE(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - BITAND(GraphTargetItem.PRECEDENCE_BITWISEAND, true), - BITOR(GraphTargetItem.PRECEDENCE_BITWISEOR, true), - XOR(GraphTargetItem.PRECEDENCE_BITWISEXOR, true), - MODULO(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_LEFT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - ASSIGN_PLUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MINUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MULTIPLY(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_DIVIDE(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITAND(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_XOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MODULO(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_LEFT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - AS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - DELETE(GraphTargetItem.PRECEDENCE_UNARY, false), - INSTANCEOF(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NAMESPACE_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEW(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPEOF(GraphTargetItem.PRECEDENCE_UNARY, false), - VOID, - ATTRIBUTE, - //Other - STRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), - COMMENT, - //XML, - IDENTIFIER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - INTEGER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - DOUBLE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - EOF, - //TRACE, - //GETURL, - //GOTOANDSTOP, - //NEXTFRAME, - //PLAY, - //PREVFRAME, - //TELLTARGET, - //STOP, - //STOPALLSOUNDS, - //TOGGLEHIGHQUALITY, - //ORD, - //CHR, - //DUPLICATEMOVIECLIP, - //STOPDRAG, - //GETTIMER, - //LOADVARIABLES, - //LOADMOVIE, - //GOTOANDPLAY, - //MBORD, - //MBCHR, - //MBLENGTH, - //MBSUBSTRING, - //RANDOM, - //REMOVEMOVIECLIP, - //STARTDRAG, - //SUBSTR, - //LENGTH, //string.length - INT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //TARGETPATH, - NUMBER_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STRING_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //IFFRAMELOADED, - INFINITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //EVAL, - UNDEFINED(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //NEWLINE, - NAN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //GETVERSION, - //CALL, - //LOADMOVIENUM, - //LOADVARIABLESNUM, - //PRINT, - //PRINTNUM, - //PRINTASBITMAP, - //PRINTASBITMAPNUM, - //UNLOADMOVIE, - //UNLOADMOVIENUM, - FINAL, - XML_STARTTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_FINISHVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_STARTFINISHTAG_END(GraphTargetItem.PRECEDENCE_PRIMARY, false), // /> - XML_COMMENT(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_CDATA(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_INSTR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_VAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // { - XML_ATTRIBUTENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa= - XML_ATTRIBUTEVALUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), // "vvv" - XML_TEXT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - XML_ATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= - XML_ATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ - XML_INSTRATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= - XML_INSTRATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ - XML_INSTRVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_FINISHVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_STARTFINISHTAG_END(GraphTargetItem.PRECEDENCE_PRIMARY, false), // /> + XML_COMMENT(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_CDATA(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_INSTR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_VAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // { + XML_ATTRIBUTENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa= + XML_ATTRIBUTEVALUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), // "vvv" + XML_TEXT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + XML_ATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= + XML_ATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ + XML_INSTRATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= + XML_INSTRATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ + XML_INSTRVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // propertyNamesList = Arrays.asList(propertyNames); - - private static final Logger logger = Logger.getLogger(Action.class.getName()); - - /** - * Constructor - * - * @param actionCode Action type identifier - * @param actionLength Length of action data - */ - public Action(int actionCode, int actionLength) { - this.actionCode = actionCode; - this.actionLength = actionLength; - } - - public Action() { - } - - /** - * Returns address of this action - * - * @return address of this action - */ - public long getAddress() { - return address; - } - - /** - * Gets all addresses which are referenced from this action and/or - * subactions - * - * @param refs list of addresses - */ - public void getRef(Set refs) { - } - - /** - * Gets all addresses which are referenced from the list of actions - * - * @param list List of actions - * @return List of addresses - */ - public static Set getActionsAllRefs(List list) { - Set ret = new HashSet<>(); - for (Action a : list) { - a.getRef(ret); - } - return ret; - } - - public int getTotalActionLength() { - return actionLength + 1 + ((actionCode >= 0x80) ? 2 : 0); - } - - /** - * Sets address of this instruction - * - * @param address Address - */ - public void setAddress(long address) { - this.address = address; - } - - /** - * Returns a string representation of the object - * - * @return a string representation of the object. - */ - @Override - public String toString() { - return "Action" + actionCode; - } - - /** - * Reads String from FlasmLexer - * - * @param lex FlasmLexer - * @return String value - * @throws IOException - * @throws ActionParseException When read object is not String - */ - protected String lexString(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_STRING) { - throw new ActionParseException("String expected", lex.yyline()); - } - return (String) symb.value; - } - - /** - * Reads Block startServer from FlasmLexer - * - * @param lex FlasmLexer - * @throws IOException - * @throws ActionParseException When read object is not Block startServer - */ - protected void lexBlockOpen(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_BLOCK_START) { - throw new ActionParseException("Block startServer ", lex.yyline()); - } - } - - /** - * Reads Identifier from FlasmLexer - * - * @param lex FlasmLexer - * @return Identifier name - * @throws IOException - * @throws ActionParseException When read object is not Identifier - */ - protected String lexIdentifier(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_IDENTIFIER) { - throw new ActionParseException("Identifier expected", lex.yyline()); - } - return (String) symb.value; - } - - /** - * Reads long value from FlasmLexer - * - * @param lex FlasmLexer - * @return long value - * @throws IOException - * @throws ActionParseException When read object is not long value - */ - protected long lexLong(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_INTEGER) { - throw new ActionParseException("Integer expected", lex.yyline()); - } - return (Long) symb.value; - } - - /** - * Reads boolean value from FlasmLexer - * - * @param lex FlasmLexer - * @return boolean value - * @throws IOException - * @throws ActionParseException When read object is not boolean value - */ - protected boolean lexBoolean(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_BOOLEAN) { - throw new ActionParseException("Boolean expected", lex.yyline()); - } - return (Boolean) symb.value; - } - - /** - * Gets action converted to bytes - * - * @param version SWF version - * @return Array of bytes - */ - public byte[] getBytes(int version) { - return surroundWithAction(new byte[0], version); - } - - /** - * Gets the length of action converted to bytes - * - * @param version SWF version - * @return Length - */ - public int getBytesLength(int version) { - return getBytes(version).length; - } - - /** - * Uptates the action length to the length calculated from action bytes - * - * @param version SWF version - */ - public void updateLength(int version) { - int length = getBytes(version).length; - actionLength = length - 1 - ((actionCode >= 0x80) ? 2 : 0); - } - - /** - * Surrounds byte array with Action header - * - * @param data Byte array - * @param version SWF version - * @return Byte array - */ - protected byte[] surroundWithAction(byte[] data, int version) { - ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - SWFOutputStream sos2 = new SWFOutputStream(baos2, version); - try { - sos2.writeUI8(actionCode); - if (actionCode >= 0x80) { - sos2.writeUI16(data.length); - } - sos2.write(data); - sos2.close(); - } catch (IOException e) { - throw new Error("This should never happen.", e); - } - return baos2.toByteArray(); - } - - /** - * Converts list of Actions to bytes - * - * @param list List of actions - * @param addZero Whether or not to add 0 UI8 value to the end - * @param version SWF version - * @return Array of bytes - */ - public static byte[] actionsToBytes(List list, boolean addZero, int version) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Action lastAction = null; - for (Action a : list) { - try { - lastAction = a; - baos.write(a.getBytes(version)); - } catch (IOException e) { - } - } - if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { - baos.write(0); - } - return baos.toByteArray(); - } - - /** - * Set addresses of actions in the list - * - * @param list List of actions - * @param baseAddress Address of first action in the list - */ - public static void setActionsAddresses(List list, long baseAddress) { - long offset = baseAddress; - for (Action a : list) { - a.setAddress(offset); - offset += a.getTotalActionLength(); - } - } - - /** - * Converts list of actions to ASM source - * - * @param listeners - * @param address - * @param list List of actions - * @param version SWF version - * @param exportMode PCode or hex? - * @return source ASM - * - */ - public static String actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode) { - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - actionsToString(listeners, address, list, version, exportMode, writer); - return writer.toString(); - } - - /** - * Converts list of actions to ASM source - * - * @param listeners - * @param address - * @param list List of actions - * @param version SWF version - * @param exportMode PCode or hex? - * @param writer - * @return GraphTextWriter - */ - public static GraphTextWriter actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - if (exportMode == ScriptExportMode.CONSTANTS) { - return constantPoolActionsToString(listeners, address, list, version, exportMode, writer); - } - - long offset; - Set importantOffsets = getActionsAllRefs(list); - /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); - if (!cps.isEmpty()) { - setConstantPool(list, cps.get(cps.size() - 1)); - }*/ - HashMap> containers = new HashMap<>(); - HashMap containersPos = new HashMap<>(); - offset = address; - int pos = 0; - boolean lastPush = false; - for (Action a : list) { - if (pos % INFORM_LISTENER_RESOLUTION == 0) { - for (DisassemblyListener listener : listeners) { - listener.progressToString(pos + 1, list.size()); - } - } - - if (exportMode == ScriptExportMode.PCODE_HEX) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("; "); - writer.appendNoHilight(Helper.bytesToHexString(a.getBytes(version))); - writer.newLine(); - } - - offset = a.getAddress(); - - if ((!(a.isIgnored())) && (a instanceof GraphSourceItemContainer)) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - containersPos.put(cnt, 0); - List sizes = cnt.getContainerSizes(); - long addr = ((Action) cnt).getAddress() + cnt.getHeaderSize(); - for (Long size : sizes) { - addr += size; - if (size == 0) { - continue; - } - if (!containers.containsKey(addr)) { - containers.put(addr, new ArrayList()); - } - containers.get(addr).add(cnt); - } - } - - if (containers.containsKey(offset)) { - for (int i = 0; i < containers.get(offset).size(); i++) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("}").newLine(); - GraphSourceItemContainer cnt = containers.get(offset).get(i); - int cntPos = containersPos.get(cnt); - writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); - cntPos++; - containersPos.put(cnt, cntPos); - } - } - - if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("loc"); - writer.appendNoHilight(Helper.formatAddress(offset)); - writer.appendNoHilight(":"); - } - - if (a.isIgnored()) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - if (!(a instanceof ActionEnd)) { - int len = a.getTotalActionLength(); - for (int i = 0; i < len; i++) { - writer.appendNoHilight("Nop").newLine(); - } - } - } else { - //if (!(a instanceof ActionNop)) { - String add = ""; - // honfika: commented out the following lines, because it makes no sense - /*if (a instanceof ActionIf) { - add = " change: " + ((ActionIf) a).getJumpOffset(); - } - if (a instanceof ActionJump) { - add = " change: " + ((ActionJump) a).getJumpOffset(); - } - add = "; ofs" + Helper.formatAddress(offset) + add; - add = "";*/ - if ((a instanceof ActionPush) && lastPush) { - writer.appendNoHilight(" "); - ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, exportMode, writer); - } else { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - - writer.append("", offset); - - int fixBranch = -1; - if (a instanceof ActionIf) { - ActionIf aif = (ActionIf) a; - if (aif.jumpUsed && !aif.ignoreUsed) { - fixBranch = 0; - } - if (!aif.jumpUsed && aif.ignoreUsed) { - fixBranch = 1; - } - } - - if (fixBranch > -1) { - writer.appendNoHilight("FFDec_DeobfuscatePop"); - if (fixBranch == 0) { //jump - writer.newLine(); - writer.appendNoHilight("Jump loc"); - writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getTotalActionLength() + ((ActionIf) a).getJumpOffset())); - } else { - //nojump, ignore - } - } else { - a.getASMSourceReplaced(list, importantOffsets, exportMode, writer); - } - writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); - writer.appendNoHilight(add); - if (!(a instanceof ActionPush)) { - writer.newLine(); - } - } - if (a instanceof ActionPush) { - lastPush = true; - } else { - lastPush = false; - } - //} - } - - offset += a.getTotalActionLength(); - pos++; - } - if (lastPush) { - writer.newLine(); - } - - if (containers.containsKey(offset)) { - for (int i = 0; i < containers.get(offset).size(); i++) { - writer.appendNoHilight("}"); - writer.newLine(); - GraphSourceItemContainer cnt = containers.get(offset).get(i); - int cntPos = containersPos.get(cnt); - writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); - cntPos++; - containersPos.put(cnt, cntPos); - } - } - - if (importantOffsets.contains(offset)) { - writer.appendNoHilight("loc"); - writer.appendNoHilight(Helper.formatAddress(offset)); - writer.appendNoHilight(":"); - writer.newLine(); - } - - return writer; - } - - public static GraphTextWriter constantPoolActionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - int poolIdx = 0; - writer.appendNoHilight(Helper.constants).newLine(); - for (Action a : list) { - if (a instanceof ActionConstantPool) { - if (poolIdx > 0) { - writer.appendNoHilight("---").newLine(); - } - - ActionConstantPool cPool = (ActionConstantPool) a; - int constIdx = 0; - for (String c : cPool.constantPool) { - writer.appendNoHilight(constIdx); - writer.appendNoHilight("|"); - writer.appendNoHilight(Helper.escapeString(c)); - writer.newLine(); - constIdx++; - } - - poolIdx++; - } - } - - return writer; - } - - /** - * Convert action to ASM source - * - * @param container - * @param knownAddreses List of important offsets to mark as labels - * @param exportMode PCode or hex? - * @return String of P-code source - */ - public String getASMSource(ActionList container, Set knownAddreses, ScriptExportMode exportMode) { - return toString(); - } - - /** - * Translates this function to stack and output. - * - * @param stack Stack - * @param output Output - * @param regNames Register names - * @param variables Variables - * @param functions Functions - * @param staticOperation the value of staticOperation - * @param path the value of path - * @throws java.lang.InterruptedException - */ - public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) throws InterruptedException { - } - - /** - * Pops long value off the stack - * - * @param stack Stack - * @return long value - */ - protected long popLong(TranslateStack stack) { - GraphTargetItem item = stack.pop(); - if (item instanceof DirectValueActionItem) { - if (((DirectValueActionItem) item).value instanceof Long) { - return (long) (Long) ((DirectValueActionItem) item).value; - } - } - return 0; - } - - /** - * Converts action index to address in the specified list of actions - * - * @param actions List of actions - * @param ip Action index - * @return address - */ - public static long ip2adr(List actions, int ip) { - /* List actions=new ArrayList(); - for(GraphSourceItem s:sources){ - if(s instanceof Action){ - actions.add((Action)s); - } - }*/ - if (ip >= actions.size()) { - if (actions.isEmpty()) { - return 0; - } - return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); - } - if (ip == -1) { - return 0; - } - return actions.get(ip).getAddress(); - } - - /** - * Converts address to action index in the specified list of actions - * - * @param actions List of actions - * @param addr Address - * @return action index - */ - public static int adr2ip(List actions, long addr) { - for (int ip = 0; ip < actions.size(); ip++) { - if (actions.get(ip).getAddress() == addr) { - return ip; - } - } - if (actions.size() > 0) { - long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); - if (addr == outpos) { - return actions.size(); - } - } - return -1; - } - - public static List actionsToTree(List actions, int version, int staticOperation, String path) throws InterruptedException { - return actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); - } - - /** - * Converts list of actions to ActionScript source code - * - * @param asm - * @param actions List of actions - * @param path - * @return source - * @throws java.lang.InterruptedException - */ - public static String actionsToSource(final ASMSource asm, final List actions, final String path) throws InterruptedException { - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - actionsToSource(asm, actions, path, writer); - return writer.toString(); - } - - /** - * Converts list of actions to ActionScript source code - * - * @param asm - * @param actions List of actions - * @param path - * @param writer - * @throws java.lang.InterruptedException - */ - public static void actionsToSource(final ASMSource asm, final List actions, final String path, GraphTextWriter writer) throws InterruptedException { - writer.suspendMeasure(); - List tree = null; - Throwable convertException = null; - int timeout = Configuration.decompilationTimeoutSingleMethod.get(); - final int version = asm == null ? SWF.DEFAULT_VERSION : asm.getSwf().version; - try { - tree = CancellableWorker.call(new Callable>() { - @Override - public List call() throws Exception { - 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); - Graph.graphToString(tree, new NulWriter(), new LocalData()); - return tree; - } - }, timeout, TimeUnit.SECONDS); - } catch (InterruptedException ex) { - throw ex; - } catch (Exception | OutOfMemoryError | StackOverflowError ex) { - if (ex instanceof TimeoutException) { - logger.log(Level.SEVERE, "Decompilation timeout in: " + path, ex); - } else { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ex); - } - convertException = ex; - Throwable cause = ex.getCause(); - if (ex instanceof ExecutionException && cause instanceof Exception) { - convertException = cause; - } - } - writer.continueMeasure(); - - if (asm != null) { - asm.getActionSourcePrefix(writer); - } - if (convertException == null) { - Graph.graphToString(tree, writer, new LocalData()); - } else if (convertException instanceof TimeoutException) { - Helper.appendTimeoutComment(writer, timeout); - } else { - Helper.appendErrorComment(writer, convertException); - } - if (asm != null) { - asm.getActionSourceSuffix(writer); - } - } - - /** - * Converts list of actions to List of treeItems - * - * @param regNames Register names - * @param variables - * @param functions - * @param actions List of actions - * @param version SWF version - * @param staticOperation - * @param path - * @return List of treeItems - * @throws java.lang.InterruptedException - */ - public static List actionsToTree(HashMap regNames, HashMap variables, HashMap functions, List actions, int version, int staticOperation, String path) throws InterruptedException { - return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path); - } - - @Override - public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException { - ActionLocalData aLocalData = (ActionLocalData) localData; - translate(stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path); - } - - @Override - public boolean isJump() { - return false; - } - - @Override - public boolean isBranch() { - return false; - } - - @Override - public boolean isExit() { - return false; - } - - @Override - public long getOffset() { - return getAddress(); - } - - @Override - public List getBranches(GraphSource code) { - return new ArrayList<>(); - } - - @Override - public boolean isIgnored() { - return ignored; - } - - @Override - public void setIgnored(boolean ignored, int pos) { - this.ignored = ignored; - } - - private static class Loop { - - public long loopContinue; - - public long loopBreak; - - public int continueCount = 0; - - public int breakCount = 0; - - public Loop(long loopContinue, long loopBreak) { - this.loopContinue = loopContinue; - this.loopBreak = loopBreak; - } - - @Override - public String toString() { - return "[Loop continue:" + loopContinue + ", break:" + loopBreak + "]"; - } - } - - private static void log(String s) { - logger.fine(s); - } - - public static List actionsPartToTree(HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException { - if (start < actions.size() && (end > 0) && (start > 0)) { - log("Entering " + start + "-" + end + (actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : "")); - } - ActionLocalData localData = new ActionLocalData(registerNames, variables, functions); - List output = new ArrayList<>(); - int ip = start; - boolean isWhile = false; - boolean isForIn = false; - GraphTargetItem inItem = null; - int loopStart = 0; - loopip: - while (ip <= end) { - - long addr = ip2adr(actions, ip); - if (ip > end) { - break; - } - if (ip >= actions.size()) { - output.add(new ScriptEndItem()); - break; - } - Action action = actions.get(ip); - if (action.isIgnored()) { - ip++; - continue; - } - if (action instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; - //List out=actionsPartToTree(new HashMap(), new HashMap(),new HashMap(), new TranslateStack(), src, ip+1,endip-1 , version); - long endAddr = action.getAddress() + cnt.getHeaderSize(); - String cntName = cnt.getName(); - List> outs = new ArrayList<>(); - HashMap variables2 = Helper.deepCopy(variables); - if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) { - for (int r = 0; r < 256; r++) { - if (variables2.containsKey("__register" + r)) { - variables2.remove("__register" + r); - } - } - } - for (long size : cnt.getContainerSizes()) { - if (size == 0) { - outs.add(new ArrayList()); - continue; - } - List out; - try { - out = ActionGraph.translateViaGraph(cnt.getRegNames(), variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName)); - } catch (OutOfMemoryError | TranslateException | StackOverflowError ex2) { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ex2); - if (ex2 instanceof OutOfMemoryError) { - Helper.freeMem(); - } - out = new ArrayList<>(); - out.add(new CommentItem(new String[]{ - "", - " * " + AppResources.translate("decompilationError"), - " * " + AppResources.translate("decompilationError.obfuscated"), - Helper.decompilationErrorAdd == null ? null : " * " + Helper.decompilationErrorAdd, - " * " + AppResources.translate("decompilationError.errorType") + ": " - + ex2.getClass().getSimpleName(), - ""})); - } - outs.add(out); - endAddr += size; - } - ((GraphSourceItemContainer) action).translateContainer(outs, stack, output, registerNames, variables, functions); - ip = adr2ip(actions, endAddr); - continue; - } - - //return in for..in - if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { - if (ip + 3 <= end) { - if ((actions.get(ip + 1) instanceof ActionEquals) || (actions.get(ip + 1) instanceof ActionEquals2)) { - if (actions.get(ip + 2) instanceof ActionNot) { - if (actions.get(ip + 3) instanceof ActionIf) { - ActionIf aif = (ActionIf) actions.get(ip + 3); - if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) { - ip += 4; - continue; - } - } - } - } - } - } - - /*ActionJump && ActionIf removed*/ - /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) { - loopStart = ip + 1; - isForIn = true; - ip += 4; - action.translate(localData, stack, output); - EnumerateActionItem en = (EnumerateActionItem) stack.peek(); - inItem = en.object; - continue; - } else*/ /*if (action instanceof ActionTry) { - ActionTry atry = (ActionTry) action; - List tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version); - ActionItem catchName; - if (atry.catchInRegisterFlag) { - catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList<>()); - } else { - catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList<>()); - } - List catchExceptions = new ArrayList(); - catchExceptions.add(catchName); - List> catchCommands = new ArrayList>(); - catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version)); - List finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version); - output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands)); - } else if (action instanceof ActionWith) { - ActionWith awith = (ActionWith) action; - List withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList() , version); //TODO:parse with actions - output.add(new WithActionItem(action, stack.pop(), withCommands)); - } else */ if (false) { - } /*if (action instanceof ActionStoreRegister) { - if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) { - action.translate(localData, stack, output); - stack.pop(); - ip++; - } else { - try { - action.translate(localData, stack, output); - } catch (Exception ex) { - // ignore - } - } - } */ /*else if (action instanceof ActionStrictEquals) { - if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) { - List caseValues = new ArrayList(); - List> caseCommands = new ArrayList>(); - caseValues.add(stack.pop()); - ActionItem switchedObject = stack.pop(); - if (output.size() > 0) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - output.remove(output.size() - 1); - } - } - int caseStart = ip + 2; - List caseBodyIps = new ArrayList(); - long defaultAddr = 0; - caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version)); - ip++; - do { - ip++; - if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) { - caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop()); - caseStart = ip + 1; - caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version)); - if (actions.get(ip + 1) instanceof ActionJump) { - defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version); - ip = adr2ip(actions, defaultAddr, version); - break; - } - } - } while (ip < end); - - for (int i = 0; i < caseBodyIps.size(); i++) { - int caseEnd = ip - 1; - if (i < caseBodyIps.size() - 1) { - caseEnd = caseBodyIps.get(i + 1) - 1; - } - caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version)); - } - output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null)); - continue; - } else { - action.translate(stack, constants, output, registerNames); - } - } */ else { - - if (action instanceof ActionStore) { - ActionStore store = (ActionStore) action; - store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize())); - ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/; - } - - try { - action.translate(localData, stack, output, staticOperation, path); - } catch (EmptyStackException ese) { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ese); - output.add(new UnsupportedActionItem(action, "Empty stack")); - } - - } - - ip++; - } - //output = checkClass(output); - log("Leaving " + start + "-" + end); - return output; - } - - public static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) { - GraphTargetItem t = ti; - if (!(t instanceof GetMemberActionItem)) { - return ti; - } - GetMemberActionItem lastMember = null; - while (((GetMemberActionItem) t).object instanceof GetMemberActionItem) { - lastMember = (GetMemberActionItem) t; - t = ((GetMemberActionItem) t).object; - } - if (((GetMemberActionItem) t).object instanceof GetVariableActionItem) { - GetVariableActionItem v = (GetVariableActionItem) ((GetMemberActionItem) t).object; - if (v.name instanceof DirectValueActionItem) { - if (((DirectValueActionItem) v.name).value instanceof String) { - if (((DirectValueActionItem) v.name).value.equals("_global")) { - GetVariableActionItem gvt = new GetVariableActionItem(null, ((GetMemberActionItem) t).memberName); - if (lastMember == null) { - return gvt; - } else { - lastMember.object = gvt; - } - } - } - } - } - return ti; - } - - public static List checkClass(List output) { - if (true) { - //return output; - } - List ret = new ArrayList<>(); - List functions = new ArrayList<>(); - List staticFunctions = new ArrayList<>(); - List> vars = new ArrayList<>(); - List> staticVars = new ArrayList<>(); - GraphTargetItem className; - GraphTargetItem extendsOp = null; - List implementsOp = new ArrayList<>(); - boolean ok = true; - int prevCount = 0; - for (GraphTargetItem t : output) { - if (t instanceof IfItem) { - IfItem it = (IfItem) t; - if (it.expression instanceof NotItem) { - NotItem nti = (NotItem) it.expression; - if ((nti.value instanceof GetMemberActionItem) || (nti.value instanceof GetVariableActionItem)) { - if (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) { - if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) { - // ignore - } else { - List parts = it.onTrue; - className = getWithoutGlobal(nti.value); - if (parts.size() >= 1) { - int ipos = 0; - while ((parts.get(ipos) instanceof IfItem) - && ((((IfItem) parts.get(ipos)).onTrue.size() == 1) && (((IfItem) parts.get(ipos)).onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ((IfItem) parts.get(ipos)).onTrue.get(0)).value instanceof NewObjectActionItem))) { - - ipos++; - } - if (parts.get(ipos) instanceof ExtendsActionItem) { - ExtendsActionItem et = (ExtendsActionItem) parts.get(ipos); - extendsOp = getWithoutGlobal(et.superclass); - ipos++; - } - if (parts.get(ipos) instanceof StoreRegisterActionItem) { - StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); - int instanceReg = sr.register.number; - if (sr.value instanceof GetMemberActionItem) { - GetMemberActionItem gm = (GetMemberActionItem) sr.value; - //gm.memberName should be "prototype" - if (gm.object instanceof TemporaryRegister) { - TemporaryRegister tm = (TemporaryRegister) gm.object; - int classReg = tm.getRegId(); - if (tm.value instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) tm.value; - if (sm.value instanceof StoreRegisterActionItem) { - sr = (StoreRegisterActionItem) sm.value; - if (sr.value instanceof FunctionActionItem) { - ((FunctionActionItem) (sr.value)).calculatedFunctionName = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; - functions.add((FunctionActionItem) sr.value); - - for (; ipos < parts.size(); ipos++) { - if (parts.get(ipos) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); - implementsOp = io.superclasses; - continue; - } - if (parts.get(ipos) instanceof SetMemberActionItem) { - sm = (SetMemberActionItem) parts.get(ipos); - int rnum = -1; - if (sm.object instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) sm.object; - if (dv.value instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) dv.value; - rnum = rn.number; - } - } - if (sm.object instanceof TemporaryRegister) { - rnum = ((TemporaryRegister) sm.object).getRegId(); - } - if (rnum == instanceReg) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - functions.add((FunctionActionItem) sm.value); - } else { - vars.add(new MyEntry<>(sm.objectName, sm.value)); - } - } else if (rnum == classReg) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - staticFunctions.add((FunctionActionItem) sm.value); - } else { - staticVars.add(new MyEntry<>(sm.objectName, sm.value)); - } - } - - } - } - - } - - } - } - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars)); - return output2; - } - } - } else if (parts.get(ipos) instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) parts.get(0); - if (sm.value instanceof FunctionActionItem) { - FunctionActionItem f = (FunctionActionItem) sm.value; - if (f.actions.isEmpty()) { - if (parts.size() == 2) { - if (parts.get(1) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem iot = (ImplementsOpActionItem) parts.get(1); - implementsOp = iot.superclasses; - } else { - ok = false; - break; - } - } - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new InterfaceActionItem(sm.objectName, implementsOp)); - return output2; - } - } - } - } - } - } else { - ok = false; - } - } else { - ok = false; - } - } else { - ok = false; - } - } else { - prevCount++; - //ok = false; - } - if (!ok) { - break; - } - } - return output; - } - - @Override - public boolean ignoredLoops() { - return false; - } - - public static void setConstantPool(List actions, ConstantPool cpool) { - for (GraphSourceItem a : actions) { - if (a instanceof ActionPush) { - if (cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } - } - if (a instanceof ActionDefineFunction) { - if (cpool != null) { - //((ActionDefineFunction) a).setConstantPool(cpool.constants,actions); - } - } - if (a instanceof ActionDefineFunction2) { - if (cpool != null) { - //((ActionDefineFunction2) a).setConstantPool(cpool.constants,actions); - } - } - } - } - - public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { - writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode)); - return writer; - } - - public static double toFloatPoint(Object o) { - if (o instanceof Double) { - return (Double) o; - } - if (o instanceof Integer) { - return (Integer) o; - } - if (o instanceof Long) { - return (Long) o; - } - if (o instanceof String) { - try { - return Double.parseDouble((String) o); - } catch (NumberFormatException nfe) { - return 0; - } - } - return 0; - } - - public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List variables) { - GraphTargetItem ret = get; - boolean boxed = false; - if (get instanceof VariableActionItem) { - boxed = true; - ret = ((VariableActionItem) ret).getBoxedValue(); - } - if (ret instanceof GetVariableActionItem) { - GetVariableActionItem gv = (GetVariableActionItem) ret; - ret = new SetVariableActionItem(null, gv.name, value); - } else if (ret instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) ret; - ret = new SetMemberActionItem(null, mem.object, mem.memberName, value); - } else if ((ret instanceof DirectValueActionItem) && ((DirectValueActionItem) ret).value instanceof RegisterNumber) { - ret = new StoreRegisterActionItem(null, (RegisterNumber) ((DirectValueActionItem) ret).value, value, false); - } else if (ret instanceof GetPropertyActionItem) { - GetPropertyActionItem gp = (GetPropertyActionItem) ret; - ret = new SetPropertyActionItem(null, gp.target, gp.propertyIndex, value); - } - if (boxed) { - GraphTargetItem b = ret; - ret = new VariableActionItem(((VariableActionItem) get).getVariableName(), value, ((VariableActionItem) get).isDefinition()); - ((VariableActionItem) ret).setBoxedValue((ActionItem) b); - variables.remove((VariableActionItem) get); - variables.add((VariableActionItem) ret); - } - return ret; - } - - @Override - public boolean isDeobfuscatePop() { - return false; - } - - @Override - public int getLine() { - return 0; - } - - @Override - public String getFile() { - return null; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.AppResources; +import com.jpexs.decompiler.flash.BaseLocalData; +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.action.model.ActionItem; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.ExtendsActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem; +import com.jpexs.decompiler.flash.action.model.NewObjectActionItem; +import com.jpexs.decompiler.flash.action.model.SetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.SetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; +import com.jpexs.decompiler.flash.action.model.TemporaryRegister; +import com.jpexs.decompiler.flash.action.model.UnsupportedActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; +import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; +import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; +import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionStore; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.helpers.collections.MyEntry; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.CommentItem; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.ScriptEndItem; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Represents one ACTIONRECORD, also has some static method to work with Actions + */ +public abstract class Action implements GraphSourceItem { + + private static final int INFORM_LISTENER_RESOLUTION = 100; + + private boolean ignored = false; + + /** + * Action type identifier + */ + public int actionCode; + + /** + * Length of action data + */ + public int actionLength; + + private long address; + + /** + * Names of ActionScript properties + */ + public static final String[] propertyNames = new String[]{ + "_X", + "_Y", + "_xscale", + "_yscale", + "_currentframe", + "_totalframes", + "_alpha", + "_visible", + "_width", + "_height", + "_rotation", + "_target", + "_framesloaded", + "_name", + "_droptarget", + "_url", + "_highquality", + "_focusrect", + "_soundbuftime", + "_quality", + "_xmouse", + "_ymouse" + }; + + public static final List propertyNamesList = Arrays.asList(propertyNames); + + private static final Logger logger = Logger.getLogger(Action.class.getName()); + + /** + * Constructor + * + * @param actionCode Action type identifier + * @param actionLength Length of action data + */ + public Action(int actionCode, int actionLength) { + this.actionCode = actionCode; + this.actionLength = actionLength; + } + + public Action() { + } + + /** + * Returns address of this action + * + * @return address of this action + */ + public long getAddress() { + return address; + } + + /** + * Gets all addresses which are referenced from this action and/or + * subactions + * + * @param refs list of addresses + */ + public void getRef(Set refs) { + } + + /** + * Gets all addresses which are referenced from the list of actions + * + * @param list List of actions + * @return List of addresses + */ + public static Set getActionsAllRefs(List list) { + Set ret = new HashSet<>(); + for (Action a : list) { + a.getRef(ret); + } + return ret; + } + + public int getTotalActionLength() { + return actionLength + 1 + ((actionCode >= 0x80) ? 2 : 0); + } + + /** + * Sets address of this instruction + * + * @param address Address + */ + public void setAddress(long address) { + this.address = address; + } + + /** + * Returns a string representation of the object + * + * @return a string representation of the object. + */ + @Override + public String toString() { + return "Action" + actionCode; + } + + /** + * Reads String from FlasmLexer + * + * @param lex FlasmLexer + * @return String value + * @throws IOException + * @throws ActionParseException When read object is not String + */ + protected String lexString(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_STRING) { + throw new ActionParseException("String expected", lex.yyline()); + } + return (String) symb.value; + } + + /** + * Reads Block startServer from FlasmLexer + * + * @param lex FlasmLexer + * @throws IOException + * @throws ActionParseException When read object is not Block startServer + */ + protected void lexBlockOpen(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_BLOCK_START) { + throw new ActionParseException("Block startServer ", lex.yyline()); + } + } + + /** + * Reads Identifier from FlasmLexer + * + * @param lex FlasmLexer + * @return Identifier name + * @throws IOException + * @throws ActionParseException When read object is not Identifier + */ + protected String lexIdentifier(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_IDENTIFIER) { + throw new ActionParseException("Identifier expected", lex.yyline()); + } + return (String) symb.value; + } + + /** + * Reads long value from FlasmLexer + * + * @param lex FlasmLexer + * @return long value + * @throws IOException + * @throws ActionParseException When read object is not long value + */ + protected long lexLong(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_INTEGER) { + throw new ActionParseException("Integer expected", lex.yyline()); + } + return (Long) symb.value; + } + + /** + * Reads boolean value from FlasmLexer + * + * @param lex FlasmLexer + * @return boolean value + * @throws IOException + * @throws ActionParseException When read object is not boolean value + */ + protected boolean lexBoolean(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_BOOLEAN) { + throw new ActionParseException("Boolean expected", lex.yyline()); + } + return (Boolean) symb.value; + } + + /** + * Gets action converted to bytes + * + * @param version SWF version + * @return Array of bytes + */ + public byte[] getBytes(int version) { + return surroundWithAction(new byte[0], version); + } + + /** + * Gets the length of action converted to bytes + * + * @param version SWF version + * @return Length + */ + public int getBytesLength(int version) { + return getBytes(version).length; + } + + /** + * Uptates the action length to the length calculated from action bytes + * + * @param version SWF version + */ + public void updateLength(int version) { + int length = getBytes(version).length; + actionLength = length - 1 - ((actionCode >= 0x80) ? 2 : 0); + } + + /** + * Surrounds byte array with Action header + * + * @param data Byte array + * @param version SWF version + * @return Byte array + */ + protected byte[] surroundWithAction(byte[] data, int version) { + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + SWFOutputStream sos2 = new SWFOutputStream(baos2, version); + try { + sos2.writeUI8(actionCode); + if (actionCode >= 0x80) { + sos2.writeUI16(data.length); + } + sos2.write(data); + sos2.close(); + } catch (IOException e) { + throw new Error("This should never happen.", e); + } + return baos2.toByteArray(); + } + + /** + * Converts list of Actions to bytes + * + * @param list List of actions + * @param addZero Whether or not to add 0 UI8 value to the end + * @param version SWF version + * @return Array of bytes + */ + public static byte[] actionsToBytes(List list, boolean addZero, int version) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Action lastAction = null; + for (Action a : list) { + try { + lastAction = a; + baos.write(a.getBytes(version)); + } catch (IOException e) { + } + } + if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { + baos.write(0); + } + return baos.toByteArray(); + } + + /** + * Set addresses of actions in the list + * + * @param list List of actions + * @param baseAddress Address of first action in the list + */ + public static void setActionsAddresses(List list, long baseAddress) { + long offset = baseAddress; + for (Action a : list) { + a.setAddress(offset); + offset += a.getTotalActionLength(); + } + } + + /** + * Converts list of actions to ASM source + * + * @param listeners + * @param address + * @param list List of actions + * @param version SWF version + * @param exportMode PCode or hex? + * @return source ASM + * + */ + public static String actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode) { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + actionsToString(listeners, address, list, version, exportMode, writer); + return writer.toString(); + } + + /** + * Converts list of actions to ASM source + * + * @param listeners + * @param address + * @param list List of actions + * @param version SWF version + * @param exportMode PCode or hex? + * @param writer + * @return GraphTextWriter + */ + public static GraphTextWriter actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + if (exportMode == ScriptExportMode.CONSTANTS) { + return constantPoolActionsToString(listeners, address, list, version, exportMode, writer); + } + + long offset; + Set importantOffsets = getActionsAllRefs(list); + /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); + if (!cps.isEmpty()) { + setConstantPool(list, cps.get(cps.size() - 1)); + }*/ + HashMap> containers = new HashMap<>(); + HashMap containersPos = new HashMap<>(); + offset = address; + int pos = 0; + boolean lastPush = false; + for (Action a : list) { + if (pos % INFORM_LISTENER_RESOLUTION == 0) { + for (DisassemblyListener listener : listeners) { + listener.progressToString(pos + 1, list.size()); + } + } + + if (exportMode == ScriptExportMode.PCODE_HEX) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("; "); + writer.appendNoHilight(Helper.bytesToHexString(a.getBytes(version))); + writer.newLine(); + } + + offset = a.getAddress(); + + if ((!(a.isIgnored())) && (a instanceof GraphSourceItemContainer)) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + containersPos.put(cnt, 0); + List sizes = cnt.getContainerSizes(); + long addr = ((Action) cnt).getAddress() + cnt.getHeaderSize(); + for (Long size : sizes) { + addr += size; + if (size == 0) { + continue; + } + if (!containers.containsKey(addr)) { + containers.put(addr, new ArrayList()); + } + containers.get(addr).add(cnt); + } + } + + if (containers.containsKey(offset)) { + for (int i = 0; i < containers.get(offset).size(); i++) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("}").newLine(); + GraphSourceItemContainer cnt = containers.get(offset).get(i); + int cntPos = containersPos.get(cnt); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); + cntPos++; + containersPos.put(cnt, cntPos); + } + } + + if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + } + + if (a.isIgnored()) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + if (!(a instanceof ActionEnd)) { + int len = a.getTotalActionLength(); + for (int i = 0; i < len; i++) { + writer.appendNoHilight("Nop").newLine(); + } + } + } else { + //if (!(a instanceof ActionNop)) { + String add = ""; + // honfika: commented out the following lines, because it makes no sense + /*if (a instanceof ActionIf) { + add = " change: " + ((ActionIf) a).getJumpOffset(); + } + if (a instanceof ActionJump) { + add = " change: " + ((ActionJump) a).getJumpOffset(); + } + add = "; ofs" + Helper.formatAddress(offset) + add; + add = "";*/ + if ((a instanceof ActionPush) && lastPush) { + writer.appendNoHilight(" "); + ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, exportMode, writer); + } else { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + + writer.append("", offset); + + int fixBranch = -1; + if (a instanceof ActionIf) { + ActionIf aif = (ActionIf) a; + if (aif.jumpUsed && !aif.ignoreUsed) { + fixBranch = 0; + } + if (!aif.jumpUsed && aif.ignoreUsed) { + fixBranch = 1; + } + } + + if (fixBranch > -1) { + writer.appendNoHilight("FFDec_DeobfuscatePop"); + if (fixBranch == 0) { //jump + writer.newLine(); + writer.appendNoHilight("Jump loc"); + writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getTotalActionLength() + ((ActionIf) a).getJumpOffset())); + } else { + //nojump, ignore + } + } else { + a.getASMSourceReplaced(list, importantOffsets, exportMode, writer); + } + writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); + writer.appendNoHilight(add); + if (!(a instanceof ActionPush)) { + writer.newLine(); + } + } + if (a instanceof ActionPush) { + lastPush = true; + } else { + lastPush = false; + } + //} + } + + offset += a.getTotalActionLength(); + pos++; + } + if (lastPush) { + writer.newLine(); + } + + if (containers.containsKey(offset)) { + for (int i = 0; i < containers.get(offset).size(); i++) { + writer.appendNoHilight("}"); + writer.newLine(); + GraphSourceItemContainer cnt = containers.get(offset).get(i); + int cntPos = containersPos.get(cnt); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); + cntPos++; + containersPos.put(cnt, cntPos); + } + } + + if (importantOffsets.contains(offset)) { + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + writer.newLine(); + } + + return writer; + } + + public static GraphTextWriter constantPoolActionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + int poolIdx = 0; + writer.appendNoHilight(Helper.constants).newLine(); + for (Action a : list) { + if (a instanceof ActionConstantPool) { + if (poolIdx > 0) { + writer.appendNoHilight("---").newLine(); + } + + ActionConstantPool cPool = (ActionConstantPool) a; + int constIdx = 0; + for (String c : cPool.constantPool) { + writer.appendNoHilight(constIdx); + writer.appendNoHilight("|"); + writer.appendNoHilight(Helper.escapeString(c)); + writer.newLine(); + constIdx++; + } + + poolIdx++; + } + } + + return writer; + } + + /** + * Convert action to ASM source + * + * @param container + * @param knownAddreses List of important offsets to mark as labels + * @param exportMode PCode or hex? + * @return String of P-code source + */ + public String getASMSource(ActionList container, Set knownAddreses, ScriptExportMode exportMode) { + return toString(); + } + + /** + * Translates this function to stack and output. + * + * @param stack Stack + * @param output Output + * @param regNames Register names + * @param variables Variables + * @param functions Functions + * @param staticOperation the value of staticOperation + * @param path the value of path + * @throws java.lang.InterruptedException + */ + public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) throws InterruptedException { + } + + /** + * Pops long value off the stack + * + * @param stack Stack + * @return long value + */ + protected long popLong(TranslateStack stack) { + GraphTargetItem item = stack.pop(); + if (item instanceof DirectValueActionItem) { + if (((DirectValueActionItem) item).value instanceof Long) { + return (long) (Long) ((DirectValueActionItem) item).value; + } + } + return 0; + } + + /** + * Converts action index to address in the specified list of actions + * + * @param actions List of actions + * @param ip Action index + * @return address + */ + public static long ip2adr(List actions, int ip) { + /* List actions=new ArrayList(); + for(GraphSourceItem s:sources){ + if(s instanceof Action){ + actions.add((Action)s); + } + }*/ + if (ip >= actions.size()) { + if (actions.isEmpty()) { + return 0; + } + return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); + } + if (ip == -1) { + return 0; + } + return actions.get(ip).getAddress(); + } + + /** + * Converts address to action index in the specified list of actions + * + * @param actions List of actions + * @param addr Address + * @return action index + */ + public static int adr2ip(List actions, long addr) { + for (int ip = 0; ip < actions.size(); ip++) { + if (actions.get(ip).getAddress() == addr) { + return ip; + } + } + if (actions.size() > 0) { + long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); + if (addr == outpos) { + return actions.size(); + } + } + return -1; + } + + public static List actionsToTree(List actions, int version, int staticOperation, String path) throws InterruptedException { + return actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); + } + + /** + * Converts list of actions to ActionScript source code + * + * @param asm + * @param actions List of actions + * @param path + * @return source + * @throws java.lang.InterruptedException + */ + public static String actionsToSource(final ASMSource asm, final List actions, final String path) throws InterruptedException { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + actionsToSource(asm, actions, path, writer); + return writer.toString(); + } + + /** + * Converts list of actions to ActionScript source code + * + * @param asm + * @param actions List of actions + * @param path + * @param writer + * @throws java.lang.InterruptedException + */ + public static void actionsToSource(final ASMSource asm, final List actions, final String path, GraphTextWriter writer) throws InterruptedException { + writer.suspendMeasure(); + List tree = null; + Throwable convertException = null; + int timeout = Configuration.decompilationTimeoutSingleMethod.get(); + final int version = asm == null ? SWF.DEFAULT_VERSION : asm.getSwf().version; + try { + tree = CancellableWorker.call(new Callable>() { + @Override + public List call() throws Exception { + 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); + Graph.graphToString(tree, new NulWriter(), new LocalData()); + return tree; + } + }, timeout, TimeUnit.SECONDS); + } catch (InterruptedException ex) { + throw ex; + } catch (Exception | OutOfMemoryError | StackOverflowError ex) { + if (ex instanceof TimeoutException) { + logger.log(Level.SEVERE, "Decompilation timeout in: " + path, ex); + } else { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ex); + } + convertException = ex; + Throwable cause = ex.getCause(); + if (ex instanceof ExecutionException && cause instanceof Exception) { + convertException = cause; + } + } + writer.continueMeasure(); + + if (asm != null) { + asm.getActionSourcePrefix(writer); + } + if (convertException == null) { + Graph.graphToString(tree, writer, new LocalData()); + } else if (convertException instanceof TimeoutException) { + Helper.appendTimeoutComment(writer, timeout); + } else { + Helper.appendErrorComment(writer, convertException); + } + if (asm != null) { + asm.getActionSourceSuffix(writer); + } + } + + /** + * Converts list of actions to List of treeItems + * + * @param regNames Register names + * @param variables + * @param functions + * @param actions List of actions + * @param version SWF version + * @param staticOperation + * @param path + * @return List of treeItems + * @throws java.lang.InterruptedException + */ + public static List actionsToTree(HashMap regNames, HashMap variables, HashMap functions, List actions, int version, int staticOperation, String path) throws InterruptedException { + return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path); + } + + @Override + public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException { + ActionLocalData aLocalData = (ActionLocalData) localData; + translate(stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path); + } + + @Override + public boolean isJump() { + return false; + } + + @Override + public boolean isBranch() { + return false; + } + + @Override + public boolean isExit() { + return false; + } + + @Override + public long getOffset() { + return getAddress(); + } + + @Override + public List getBranches(GraphSource code) { + return new ArrayList<>(); + } + + @Override + public boolean isIgnored() { + return ignored; + } + + @Override + public void setIgnored(boolean ignored, int pos) { + this.ignored = ignored; + } + + private static class Loop { + + public long loopContinue; + + public long loopBreak; + + public int continueCount = 0; + + public int breakCount = 0; + + public Loop(long loopContinue, long loopBreak) { + this.loopContinue = loopContinue; + this.loopBreak = loopBreak; + } + + @Override + public String toString() { + return "[Loop continue:" + loopContinue + ", break:" + loopBreak + "]"; + } + } + + private static void log(String s) { + logger.fine(s); + } + + public static List actionsPartToTree(HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException { + if (start < actions.size() && (end > 0) && (start > 0)) { + log("Entering " + start + "-" + end + (actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : "")); + } + ActionLocalData localData = new ActionLocalData(registerNames, variables, functions); + List output = new ArrayList<>(); + int ip = start; + boolean isWhile = false; + boolean isForIn = false; + GraphTargetItem inItem = null; + int loopStart = 0; + loopip: + while (ip <= end) { + + long addr = ip2adr(actions, ip); + if (ip > end) { + break; + } + if (ip >= actions.size()) { + output.add(new ScriptEndItem()); + break; + } + Action action = actions.get(ip); + if (action.isIgnored()) { + ip++; + continue; + } + if (action instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; + //List out=actionsPartToTree(new HashMap(), new HashMap(),new HashMap(), new TranslateStack(), src, ip+1,endip-1 , version); + long endAddr = action.getAddress() + cnt.getHeaderSize(); + String cntName = cnt.getName(); + List> outs = new ArrayList<>(); + HashMap variables2 = Helper.deepCopy(variables); + if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) { + for (int r = 0; r < 256; r++) { + if (variables2.containsKey("__register" + r)) { + variables2.remove("__register" + r); + } + } + } + for (long size : cnt.getContainerSizes()) { + if (size == 0) { + outs.add(new ArrayList()); + continue; + } + List out; + try { + out = ActionGraph.translateViaGraph(cnt.getRegNames(), variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName)); + } catch (OutOfMemoryError | TranslateException | StackOverflowError ex2) { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ex2); + if (ex2 instanceof OutOfMemoryError) { + Helper.freeMem(); + } + out = new ArrayList<>(); + out.add(new CommentItem(new String[]{ + "", + " * " + AppResources.translate("decompilationError"), + " * " + AppResources.translate("decompilationError.obfuscated"), + Helper.decompilationErrorAdd == null ? null : " * " + Helper.decompilationErrorAdd, + " * " + AppResources.translate("decompilationError.errorType") + ": " + + ex2.getClass().getSimpleName(), + ""})); + } + outs.add(out); + endAddr += size; + } + ((GraphSourceItemContainer) action).translateContainer(outs, stack, output, registerNames, variables, functions); + ip = adr2ip(actions, endAddr); + continue; + } + + //return in for..in + if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { + if (ip + 3 <= end) { + if ((actions.get(ip + 1) instanceof ActionEquals) || (actions.get(ip + 1) instanceof ActionEquals2)) { + if (actions.get(ip + 2) instanceof ActionNot) { + if (actions.get(ip + 3) instanceof ActionIf) { + ActionIf aif = (ActionIf) actions.get(ip + 3); + if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) { + ip += 4; + continue; + } + } + } + } + } + } + + /*ActionJump && ActionIf removed*/ + /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) { + loopStart = ip + 1; + isForIn = true; + ip += 4; + action.translate(localData, stack, output); + EnumerateActionItem en = (EnumerateActionItem) stack.peek(); + inItem = en.object; + continue; + } else*/ /*if (action instanceof ActionTry) { + ActionTry atry = (ActionTry) action; + List tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version); + ActionItem catchName; + if (atry.catchInRegisterFlag) { + catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList()); + } else { + catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList()); + } + List catchExceptions = new ArrayList(); + catchExceptions.add(catchName); + List> catchCommands = new ArrayList>(); + catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version)); + List finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version); + output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands)); + } else if (action instanceof ActionWith) { + ActionWith awith = (ActionWith) action; + List withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList() , version); //TODO:parse with actions + output.add(new WithActionItem(action, stack.pop(), withCommands)); + } else */ if (false) { + } /*if (action instanceof ActionStoreRegister) { + if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) { + action.translate(localData, stack, output); + stack.pop(); + ip++; + } else { + try { + action.translate(localData, stack, output); + } catch (Exception ex) { + // ignore + } + } + } */ /*else if (action instanceof ActionStrictEquals) { + if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) { + List caseValues = new ArrayList(); + List> caseCommands = new ArrayList>(); + caseValues.add(stack.pop()); + ActionItem switchedObject = stack.pop(); + if (output.size() > 0) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + output.remove(output.size() - 1); + } + } + int caseStart = ip + 2; + List caseBodyIps = new ArrayList(); + long defaultAddr = 0; + caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version)); + ip++; + do { + ip++; + if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) { + caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop()); + caseStart = ip + 1; + caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version)); + if (actions.get(ip + 1) instanceof ActionJump) { + defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version); + ip = adr2ip(actions, defaultAddr, version); + break; + } + } + } while (ip < end); + + for (int i = 0; i < caseBodyIps.size(); i++) { + int caseEnd = ip - 1; + if (i < caseBodyIps.size() - 1) { + caseEnd = caseBodyIps.get(i + 1) - 1; + } + caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version)); + } + output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null)); + continue; + } else { + action.translate(stack, constants, output, registerNames); + } + } */ else { + + if (action instanceof ActionStore) { + ActionStore store = (ActionStore) action; + store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize())); + ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/; + } + + try { + action.translate(localData, stack, output, staticOperation, path); + } catch (EmptyStackException ese) { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ese); + output.add(new UnsupportedActionItem(action, "Empty stack")); + } + + } + + ip++; + } + //output = checkClass(output); + log("Leaving " + start + "-" + end); + return output; + } + + public static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) { + GraphTargetItem t = ti; + if (!(t instanceof GetMemberActionItem)) { + return ti; + } + GetMemberActionItem lastMember = null; + while (((GetMemberActionItem) t).object instanceof GetMemberActionItem) { + lastMember = (GetMemberActionItem) t; + t = ((GetMemberActionItem) t).object; + } + if (((GetMemberActionItem) t).object instanceof GetVariableActionItem) { + GetVariableActionItem v = (GetVariableActionItem) ((GetMemberActionItem) t).object; + if (v.name instanceof DirectValueActionItem) { + if (((DirectValueActionItem) v.name).value instanceof String) { + if (((DirectValueActionItem) v.name).value.equals("_global")) { + GetVariableActionItem gvt = new GetVariableActionItem(null, ((GetMemberActionItem) t).memberName); + if (lastMember == null) { + return gvt; + } else { + lastMember.object = gvt; + } + } + } + } + } + return ti; + } + + public static List checkClass(List output) { + if (true) { + //return output; + } + List ret = new ArrayList<>(); + List functions = new ArrayList<>(); + List staticFunctions = new ArrayList<>(); + List> vars = new ArrayList<>(); + List> staticVars = new ArrayList<>(); + GraphTargetItem className; + GraphTargetItem extendsOp = null; + List implementsOp = new ArrayList<>(); + boolean ok = true; + int prevCount = 0; + for (GraphTargetItem t : output) { + if (t instanceof IfItem) { + IfItem it = (IfItem) t; + if (it.expression instanceof NotItem) { + NotItem nti = (NotItem) it.expression; + if ((nti.value instanceof GetMemberActionItem) || (nti.value instanceof GetVariableActionItem)) { + if (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) { + if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) { + // ignore + } else { + List parts = it.onTrue; + className = getWithoutGlobal(nti.value); + if (parts.size() >= 1) { + int ipos = 0; + while ((parts.get(ipos) instanceof PopItem) || ((parts.get(ipos) instanceof IfItem) + && ((((IfItem) parts.get(ipos)).onTrue.size() == 1) && (((IfItem) parts.get(ipos)).onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ((IfItem) parts.get(ipos)).onTrue.get(0)).value instanceof NewObjectActionItem)))) { + + ipos++; + } + if (parts.get(ipos) instanceof ExtendsActionItem) { + ExtendsActionItem et = (ExtendsActionItem) parts.get(ipos); + extendsOp = getWithoutGlobal(et.superclass); + ipos++; + } + if (parts.get(ipos) instanceof StoreRegisterActionItem) { + StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); + int instanceReg = sr.register.number; + if (sr.value instanceof GetMemberActionItem) { + GetMemberActionItem gm = (GetMemberActionItem) sr.value; + //gm.memberName should be "prototype" + if (gm.object instanceof TemporaryRegister) { + TemporaryRegister tm = (TemporaryRegister) gm.object; + int classReg = tm.getRegId(); + if (tm.value instanceof SetMemberActionItem) { + SetMemberActionItem sm = (SetMemberActionItem) tm.value; + if (sm.value instanceof StoreRegisterActionItem) { + sr = (StoreRegisterActionItem) sm.value; + if (sr.value instanceof FunctionActionItem) { + ((FunctionActionItem) (sr.value)).calculatedFunctionName = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; + functions.add((FunctionActionItem) sr.value); + + for (; ipos < parts.size(); ipos++) { + if (parts.get(ipos) instanceof ImplementsOpActionItem) { + ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); + implementsOp = io.superclasses; + continue; + } + if (parts.get(ipos) instanceof SetMemberActionItem) { + sm = (SetMemberActionItem) parts.get(ipos); + int rnum = -1; + if (sm.object instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) sm.object; + if (dv.value instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) dv.value; + rnum = rn.number; + } + } + if (sm.object instanceof TemporaryRegister) { + rnum = ((TemporaryRegister) sm.object).getRegId(); + } + if (rnum == instanceReg) { + if (sm.value instanceof FunctionActionItem) { + ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; + functions.add((FunctionActionItem) sm.value); + } else { + vars.add(new MyEntry<>(sm.objectName, sm.value)); + } + } else if (rnum == classReg) { + if (sm.value instanceof FunctionActionItem) { + ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; + staticFunctions.add((FunctionActionItem) sm.value); + } else { + staticVars.add(new MyEntry<>(sm.objectName, sm.value)); + } + } + + } + } + + } + + } + } + List output2 = new ArrayList<>(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars)); + return output2; + } + } + } else if (parts.get(ipos) instanceof SetMemberActionItem) { + SetMemberActionItem sm = (SetMemberActionItem) parts.get(0); + if (sm.value instanceof FunctionActionItem) { + FunctionActionItem f = (FunctionActionItem) sm.value; + if (f.actions.isEmpty()) { + if (parts.size() == 2) { + if (parts.get(1) instanceof ImplementsOpActionItem) { + ImplementsOpActionItem iot = (ImplementsOpActionItem) parts.get(1); + implementsOp = iot.superclasses; + } else { + ok = false; + break; + } + } + List output2 = new ArrayList<>(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new InterfaceActionItem(sm.objectName, implementsOp)); + return output2; + } + } + } + } + } + } else { + ok = false; + } + } else { + ok = false; + } + } else { + ok = false; + } + } else if (!(t instanceof PopItem)) { + prevCount++; + //ok = false; + } + if (!ok) { + break; + } + } + return output; + } + + @Override + public boolean ignoredLoops() { + return false; + } + + public static void setConstantPool(List actions, ConstantPool cpool) { + for (GraphSourceItem a : actions) { + if (a instanceof ActionPush) { + if (cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } + } + if (a instanceof ActionDefineFunction) { + if (cpool != null) { + //((ActionDefineFunction) a).setConstantPool(cpool.constants,actions); + } + } + if (a instanceof ActionDefineFunction2) { + if (cpool != null) { + //((ActionDefineFunction2) a).setConstantPool(cpool.constants,actions); + } + } + } + } + + public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { + writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode)); + return writer; + } + + public static double toFloatPoint(Object o) { + if (o instanceof Double) { + return (Double) o; + } + if (o instanceof Integer) { + return (Integer) o; + } + if (o instanceof Long) { + return (Long) o; + } + if (o instanceof String) { + try { + return Double.parseDouble((String) o); + } catch (NumberFormatException nfe) { + return 0; + } + } + return 0; + } + + public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List variables) { + GraphTargetItem ret = get; + boolean boxed = false; + if (get instanceof VariableActionItem) { + boxed = true; + ret = ((VariableActionItem) ret).getBoxedValue(); + } + if (ret instanceof GetVariableActionItem) { + GetVariableActionItem gv = (GetVariableActionItem) ret; + ret = new SetVariableActionItem(null, gv.name, value); + } else if (ret instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) ret; + ret = new SetMemberActionItem(null, mem.object, mem.memberName, value); + } else if ((ret instanceof DirectValueActionItem) && ((DirectValueActionItem) ret).value instanceof RegisterNumber) { + ret = new StoreRegisterActionItem(null, (RegisterNumber) ((DirectValueActionItem) ret).value, value, false); + } else if (ret instanceof GetPropertyActionItem) { + GetPropertyActionItem gp = (GetPropertyActionItem) ret; + ret = new SetPropertyActionItem(null, gp.target, gp.propertyIndex, value); + } + if (boxed) { + GraphTargetItem b = ret; + ret = new VariableActionItem(((VariableActionItem) get).getVariableName(), value, ((VariableActionItem) get).isDefinition()); + ((VariableActionItem) ret).setBoxedValue((ActionItem) b); + variables.remove((VariableActionItem) get); + variables.add((VariableActionItem) ret); + } + return ret; + } + + @Override + public boolean isDeobfuscatePop() { + return false; + } + + @Override + public int getLine() { + return 0; + } + + @Override + public String getFile() { + return null; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java index c8ad89d07..599018dc0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -1,487 +1,487 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action; - -import com.jpexs.decompiler.flash.BaseLocalData; -import com.jpexs.decompiler.flash.FinalProcessLocalData; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; -import com.jpexs.decompiler.flash.action.model.FunctionActionItem; -import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem; -import com.jpexs.decompiler.flash.action.model.SetTargetActionItem; -import com.jpexs.decompiler.flash.action.model.SetTypeActionItem; -import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem; -import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem; -import com.jpexs.decompiler.flash.action.model.operations.StrictEqActionItem; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSource; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.Loop; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.BreakItem; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.SwitchItem; -import com.jpexs.decompiler.graph.model.WhileItem; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class ActionGraph extends Graph { - - public ActionGraph(List code, HashMap registerNames, HashMap variables, HashMap functions, int version) { - super(new ActionGraphSource(code, version, registerNames, variables, functions), new ArrayList()); - //this.version = version; - /*heads = makeGraph(code, new ArrayList()); - for (GraphPart head : heads) { - fixGraph(head); - makeMulti(head, new ArrayList()); - }*/ - } - - public static List translateViaGraph(HashMap registerNames, HashMap variables, HashMap functions, List code, int version, int staticOperation, String path) throws InterruptedException { - - ActionGraph g = new ActionGraph(code, registerNames, variables, functions, version); - ActionLocalData localData = new ActionLocalData(registerNames); - g.init(localData); - return g.translate(localData, staticOperation, path); - } - - @Override - public void finalProcessStack(TranslateStack stack, List output) { - if (stack.size() > 0) { - for (int i = stack.size() - 1; i >= 0; i--) { - //System.err.println(stack.get(i)); - if (stack.get(i) instanceof FunctionActionItem) { - FunctionActionItem f = (FunctionActionItem) stack.remove(i); - if (!output.contains(f)) { - output.add(0, f); - } - } - } - } - } - - @Override - protected void finalProcess(List list, int level, FinalProcessLocalData localData) { - super.finalProcess(list, level, localData); - List ret = Action.checkClass(list); - if (ret != list) { - list.clear(); - list.addAll(ret); - } - int targetStart; - int targetEnd; - - boolean again; - do { - again = false; - targetStart = -1; - targetEnd = -1; - GraphTargetItem targetStartItem = null; - GraphTargetItem target = null; - for (int t = 0; t < list.size(); t++) { - GraphTargetItem it = list.get(t); - if (it instanceof SetTargetActionItem) { - SetTargetActionItem st = (SetTargetActionItem) it; - if (st.target.isEmpty()) { - if (targetStart > -1) { - targetEnd = t; - break; - } - } else { - target = new DirectValueActionItem(null, 0, st.target, new ArrayList<>()); - targetStart = t; - targetStartItem = it; - } - } - if (it instanceof SetTarget2ActionItem) { - SetTarget2ActionItem st = (SetTarget2ActionItem) it; - if ((st.target instanceof DirectValueActionItem) && st.target.getResult().equals("")) { - if (targetStart > -1) { - targetEnd = t; - break; - } - } else { - targetStart = t; - target = st.target; - targetStartItem = it; - } - } - } - if ((targetStart > -1) && (targetEnd > -1)) { - List newlist = new ArrayList<>(); - for (int i = 0; i < targetStart; i++) { - newlist.add(list.get(i)); - } - List tellist = new ArrayList<>(); - for (int i = targetStart + 1; i < targetEnd; i++) { - tellist.add(list.get(i)); - } - newlist.add(new TellTargetActionItem(targetStartItem.src, target, tellist)); - for (int i = targetEnd + 1; i < list.size(); i++) { - newlist.add(list.get(i)); - } - list.clear(); - list.addAll(newlist); - again = true; - } - } while (again); - for (int t = 0; t < list.size(); t++) { - GraphTargetItem it = list.get(t); - - if (it instanceof WhileItem) { - WhileItem wi = (WhileItem) it; - if ((!wi.commands.isEmpty()) && (wi.commands.get(0) instanceof SetTypeActionItem)) { - SetTypeActionItem sti = (SetTypeActionItem) wi.commands.get(0); - if (wi.expression.get(wi.expression.size() - 1) instanceof NeqActionItem) { - NeqActionItem ne = (NeqActionItem) wi.expression.get(wi.expression.size() - 1); - if (ne.rightSide instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide; - if (dv.value instanceof Null) { - GraphTargetItem en = ne.leftSide; - if (en instanceof StoreRegisterActionItem) { - en = ((StoreRegisterActionItem) en).value; - } - if (en instanceof EnumerateActionItem) { - EnumerateActionItem eti = (EnumerateActionItem) en; - list.remove(t); - wi.commands.remove(0); - list.add(t, new ForInActionItem(null, wi.loop, sti.getObject(), eti.object, wi.commands)); - } - } - } - } - } - - } - } - //detectChained(list, temporaryRegisters); - } - - @Override - protected List checkPrecoNextParts(GraphPart part) { - List items = getPartItems(part); - part = makeMultiPart(part); - if (items.size() > 1) { - if (items.get(items.size() - 1) instanceof ActionIf) { - if (items.get(items.size() - 2) instanceof ActionStrictEquals) { - List storeRegisters = new ArrayList<>(); - for (GraphSourceItem s : items) { - if (s instanceof ActionStoreRegister) { - ActionStoreRegister sr = (ActionStoreRegister) s; - storeRegisters.add(sr.registerNumber); - } - } - if (!storeRegisters.isEmpty()) { - List caseBodies = new ArrayList<>(); - boolean proceed = false; - do { - proceed = false; - caseBodies.add(part.nextParts.get(0)); //jump - part = part.nextParts.get(1); //nojump - items = getPartItems(part); - part = makeMultiPart(part); - if (!items.isEmpty()) { - if (items.get(0) instanceof ActionPush) { - ActionPush pu = (ActionPush) items.get(0); - if (!pu.values.isEmpty()) { - if (pu.values.get(0) instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) pu.values.get(0); - if (storeRegisters.contains(rn.number)) { - storeRegisters.clear(); - storeRegisters.add(rn.number); - if (items.get(items.size() - 1) instanceof ActionIf) { - if (items.size() > 1) { - if (items.get(items.size() - 2) instanceof ActionStrictEquals) { - proceed = true; - } - } - } - } - } - } - } - } - } while (proceed); - - if (caseBodies.size() > 1) { - caseBodies.add(part); //TODO: properly detect default clause (?) - return caseBodies; - } - } - } - } - } - return null; - } - - @Override - protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - StoreRegisterActionItem str = (StoreRegisterActionItem) output.get(output.size() - 1); - if (str.value instanceof EnumerateActionItem) { - output.remove(output.size() - 1); - } - } - } - List ret = null; - if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && (stack.peek() instanceof StrictEqActionItem)) { - - GraphTargetItem switchedObject = null; - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - switchedObject = ((StoreRegisterActionItem) output.get(output.size() - 1)).value; - } - } - if (switchedObject == null) { - switchedObject = new DirectValueActionItem(null, -1, new Null(), null); - } - HashMap caseValuesMap = new HashMap<>(); - - int pos = 0; - StrictEqActionItem set = (StrictEqActionItem) stack.pop(); - caseValuesMap.put(pos, set.rightSide); - if (set.leftSide instanceof StoreRegisterActionItem) { - switchedObject = ((StoreRegisterActionItem) set.leftSide).value; - } - //GraphPart switchLoc = part.nextParts.get(1).nextParts.get(0); - List caseBodyParts = new ArrayList<>(); - caseBodyParts.add(part.nextParts.get(0)); - GraphTargetItem top = null; - int cnt = 1; - while (part.nextParts.size() > 1 - && part.nextParts.get(1).getHeight() > 1 - && code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end) instanceof ActionIf - && ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) { - cnt++; - part = part.nextParts.get(1); - pos++; - caseBodyParts.add(part.nextParts.get(0)); - - set = (StrictEqActionItem) top; - caseValuesMap.put(pos, set.rightSide); - } - if (cnt == 1) { - stack.push(set); - } else { - part = part.nextParts.get(1); - - GraphPart defaultPart = part; //21-21 - //caseBodyParts.add(defaultPart); - - List defaultAndLastPart = new ArrayList<>(); - defaultAndLastPart.add(defaultPart); - defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1)); - - GraphPart defaultPart2 = getCommonPart(localData, defaultAndLastPart, loops);//34-37 - - List defaultCommands = new ArrayList<>(); - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(defaultPart2); - defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path); - - List loopContinues = new ArrayList<>(); - for (Loop l : loops) { - if (l.loopContinue != null) { - loopContinues.add(l.loopContinue); - } - } - - List breakParts = new ArrayList<>(); - /*for (int g = 0; g < caseBodyParts.size(); g++) { - if (g < caseBodyParts.size() - 1) { - if (caseBodyParts.get(g).leadsTo(code, caseBodyParts.get(g + 1), loops)) { - continue; - } - } - GraphPart nsp = caseBodyParts.get(g).getNextSuperPartPath(loopContinues); - if (nsp != null) { - breakParts.add(nsp); - } - } - Collections.sort(breakParts, new Comparator() { - @Override - public int compare(GraphPart o1, GraphPart o2) { - return o2.path.length() - o1.path.length(); - } - });*/ - - //GraphPart breakPart = breakParts.isEmpty() ? null : breakParts.get(0); - List mcp = new ArrayList<>(); - mcp.addAll(caseBodyParts); - if (defaultPart2 != null) { - mcp.add(defaultPart2); - } - GraphPart breakPart = getMostCommonPart(localData, mcp, loops); - if ((defaultPart2 != breakPart) && (defaultCommands.isEmpty())) { - defaultPart = defaultPart2; - } - - List caseValues = new ArrayList<>(); - for (int i = 0; i < caseBodyParts.size(); i++) { - if (caseValuesMap.containsKey(i)) { - caseValues.add(caseValuesMap.get(i)); - } else { - continue; - } - } - - List> caseCommands = new ArrayList<>(); - GraphPart next = null; - - next = breakPart; - - GraphTargetItem ti = checkLoop(next, stopPart, loops); - currentLoop = new Loop(loops.size(), null, next); - currentLoop.phase = 1; - loops.add(currentLoop); - //switchLoc.getNextPartPath(new ArrayList()); - List valuesMapping = new ArrayList<>(); - List caseBodies = new ArrayList<>(); - for (int i = 0; i < caseValues.size(); i++) { - GraphPart cur = caseBodyParts.get(i); - if (!caseBodies.contains(cur)) { - caseBodies.add(cur); - } - valuesMapping.add(caseBodies.indexOf(cur)); - } - - if (defaultPart == breakPart) { - defaultPart = null; - } - if ((defaultPart != null) && (defaultCommands.isEmpty())) { - List stopPart2x = new ArrayList<>(stopPart); - stopPart2x.add(next); - defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path); - } - - if (!defaultCommands.isEmpty()) { - if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) { - BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1); - if (bi.loopId == currentLoop.id) { - defaultCommands.remove(defaultCommands.size() - 1); - } - } - } - - List ignored = new ArrayList<>(); - for (Loop l : loops) { - ignored.add(l.loopContinue); - } - - for (int i = 0; i < caseBodies.size(); i++) { - List cc = new ArrayList<>(); - GraphPart nextCase = null; - nextCase = next; - if (next != null) { - if (i < caseBodies.size() - 1) { - if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) { - cc.add(new BreakItem(null, currentLoop.id)); - } else { - nextCase = caseBodies.get(i + 1); - } - } else if (!defaultCommands.isEmpty()) { - if (!caseBodies.get(i).leadsTo(localData, this, code, defaultPart, loops)) { - cc.add(new BreakItem(null, currentLoop.id)); - } else { - nextCase = defaultPart; - } - } - } - List stopPart2x = new ArrayList<>(stopPart); - //stopPart2.add(nextCase); - for (GraphPart b : caseBodies) { - if (b != caseBodies.get(i)) { - stopPart2x.add(b); - } - } - if (defaultPart != null) { - stopPart2x.add(defaultPart); - } - if (breakPart != null) { - stopPart2x.add(breakPart); - } - cc.addAll(0, printGraph(localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); - if (cc.size() >= 2) { - if (cc.get(cc.size() - 1) instanceof BreakItem) { - if ((cc.get(cc.size() - 2) instanceof ContinueItem) || (cc.get(cc.size() - 2) instanceof BreakItem)) { - cc.remove(cc.size() - 1); - } - } - } - caseCommands.add(cc); - } - ret = new ArrayList<>(); - ret.addAll(output); - SwitchItem sti = new SwitchItem(null, currentLoop, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping); - ret.add(sti); - currentLoop.phase = 2; - if (next != null) { - if (ti != null) { - ret.add(ti); - } else { - ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); - } - } - } - } - return ret; - } - - @Override - protected int checkIp(int ip) { - int oldIp = ip; - //return in for..in - GraphSourceItem action = code.get(ip); - if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { - if (ip + 3 < code.size()) { - if ((code.get(ip + 1) instanceof ActionEquals) || (code.get(ip + 1) instanceof ActionEquals2)) { - if (code.get(ip + 2) instanceof ActionNot) { - if (code.get(ip + 3) instanceof ActionIf) { - ActionIf aif = (ActionIf) code.get(ip + 3); - if (code.adr2pos(code.pos2adr(ip + 4) + aif.getJumpOffset()) == ip) { - ip += 4; - } - } - } - } - } - } - if (oldIp != ip) { - return checkIp(ip); - } - return ip; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.BaseLocalData; +import com.jpexs.decompiler.flash.FinalProcessLocalData; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem; +import com.jpexs.decompiler.flash.action.model.SetTargetActionItem; +import com.jpexs.decompiler.flash.action.model.SetTypeActionItem; +import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem; +import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem; +import com.jpexs.decompiler.flash.action.model.operations.StrictEqActionItem; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphPart; +import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.Loop; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.BreakItem; +import com.jpexs.decompiler.graph.model.ContinueItem; +import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.SwitchItem; +import com.jpexs.decompiler.graph.model.WhileItem; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class ActionGraph extends Graph { + + public ActionGraph(List code, HashMap registerNames, HashMap variables, HashMap functions, int version) { + super(new ActionGraphSource(code, version, registerNames, variables, functions), new ArrayList()); + //this.version = version; + /*heads = makeGraph(code, new ArrayList()); + for (GraphPart head : heads) { + fixGraph(head); + makeMulti(head, new ArrayList()); + }*/ + } + + public static List translateViaGraph(HashMap registerNames, HashMap variables, HashMap functions, List code, int version, int staticOperation, String path) throws InterruptedException { + + ActionGraph g = new ActionGraph(code, registerNames, variables, functions, version); + ActionLocalData localData = new ActionLocalData(registerNames); + g.init(localData); + return g.translate(localData, staticOperation, path); + } + + @Override + public void finalProcessStack(TranslateStack stack, List output) { + if (stack.size() > 0) { + for (int i = stack.size() - 1; i >= 0; i--) { + //System.err.println(stack.get(i)); + if (stack.get(i) instanceof FunctionActionItem) { + FunctionActionItem f = (FunctionActionItem) stack.remove(i); + if (!output.contains(f)) { + output.add(0, f); + } + } + } + } + } + + @Override + protected void finalProcess(List list, int level, FinalProcessLocalData localData) { + List ret = Action.checkClass(list); + if (ret != list) { + list.clear(); + list.addAll(ret); + } + int targetStart; + int targetEnd; + + boolean again; + do { + again = false; + targetStart = -1; + targetEnd = -1; + GraphTargetItem targetStartItem = null; + GraphTargetItem target = null; + for (int t = 0; t < list.size(); t++) { + GraphTargetItem it = list.get(t); + if (it instanceof SetTargetActionItem) { + SetTargetActionItem st = (SetTargetActionItem) it; + if (st.target.isEmpty()) { + if (targetStart > -1) { + targetEnd = t; + break; + } + } else { + target = new DirectValueActionItem(null, 0, st.target, new ArrayList()); + targetStart = t; + targetStartItem = it; + } + } + if (it instanceof SetTarget2ActionItem) { + SetTarget2ActionItem st = (SetTarget2ActionItem) it; + if ((st.target instanceof DirectValueActionItem) && st.target.getResult().equals("")) { + if (targetStart > -1) { + targetEnd = t; + break; + } + } else { + targetStart = t; + target = st.target; + targetStartItem = it; + } + } + } + if ((targetStart > -1) && (targetEnd > -1)) { + List newlist = new ArrayList<>(); + for (int i = 0; i < targetStart; i++) { + newlist.add(list.get(i)); + } + List tellist = new ArrayList<>(); + for (int i = targetStart + 1; i < targetEnd; i++) { + tellist.add(list.get(i)); + } + newlist.add(new TellTargetActionItem(targetStartItem.src, target, tellist)); + for (int i = targetEnd + 1; i < list.size(); i++) { + newlist.add(list.get(i)); + } + list.clear(); + list.addAll(newlist); + again = true; + } + } while (again); + for (int t = 1/*not first*/; t < list.size(); t++) { + GraphTargetItem it = list.get(t); + if (it instanceof WhileItem) { + WhileItem wi = (WhileItem) it; + if ((!wi.commands.isEmpty()) && (wi.commands.get(0) instanceof SetTypeActionItem)) { + SetTypeActionItem sti = (SetTypeActionItem) wi.commands.get(0); + if (wi.expression.get(wi.expression.size() - 1) instanceof NeqActionItem) { + NeqActionItem ne = (NeqActionItem) wi.expression.get(wi.expression.size() - 1); + if (ne.rightSide instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide; + if (dv.value instanceof Null) { + GraphTargetItem en = list.get(t - 1); + if (en instanceof EnumerateActionItem) { + EnumerateActionItem eti = (EnumerateActionItem) en; + list.remove(t); + wi.commands.remove(0); + list.add(t, new ForInActionItem(null, wi.loop, sti.getObject(), eti.object, wi.commands)); + list.remove(t - 1); + t--; + } + } + + } + } + } + + } + } + //Handle for loops at the end: + super.finalProcess(list, level, localData); + } + + @Override + protected List checkPrecoNextParts(GraphPart part) { + List items = getPartItems(part); + part = makeMultiPart(part); + if (items.size() > 1) { + if (items.get(items.size() - 1) instanceof ActionIf) { + if (items.get(items.size() - 2) instanceof ActionStrictEquals) { + List storeRegisters = new ArrayList<>(); + for (GraphSourceItem s : items) { + if (s instanceof ActionStoreRegister) { + ActionStoreRegister sr = (ActionStoreRegister) s; + storeRegisters.add(sr.registerNumber); + } + } + if (!storeRegisters.isEmpty()) { + List caseBodies = new ArrayList<>(); + boolean proceed = false; + do { + proceed = false; + caseBodies.add(part.nextParts.get(0)); //jump + part = part.nextParts.get(1); //nojump + items = getPartItems(part); + part = makeMultiPart(part); + if (!items.isEmpty()) { + if (items.get(0) instanceof ActionPush) { + ActionPush pu = (ActionPush) items.get(0); + if (!pu.values.isEmpty()) { + if (pu.values.get(0) instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) pu.values.get(0); + if (storeRegisters.contains(rn.number)) { + storeRegisters.clear(); + storeRegisters.add(rn.number); + if (items.get(items.size() - 1) instanceof ActionIf) { + if (items.size() > 1) { + if (items.get(items.size() - 2) instanceof ActionStrictEquals) { + proceed = true; + } + } + } + } + } + } + } + } + } while (proceed); + + if (caseBodies.size() > 1) { + caseBodies.add(part); //TODO: properly detect default clause (?) + return caseBodies; + } + } + } + } + } + return null; + } + + @Override + protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { + if (!output.isEmpty()) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + StoreRegisterActionItem str = (StoreRegisterActionItem) output.get(output.size() - 1); + if (str.value instanceof EnumerateActionItem) { + output.remove(output.size() - 1); + } + } + } + List ret = null; + if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && (stack.peek() instanceof StrictEqActionItem)) { + + GraphTargetItem switchedObject = null; + if (!output.isEmpty()) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + switchedObject = ((StoreRegisterActionItem) output.get(output.size() - 1)).value; + } + } + if (switchedObject == null) { + switchedObject = new DirectValueActionItem(null, -1, new Null(), null); + } + HashMap caseValuesMap = new HashMap<>(); + + int pos = 0; + StrictEqActionItem set = (StrictEqActionItem) stack.pop(); + caseValuesMap.put(pos, set.rightSide); + if (set.leftSide instanceof StoreRegisterActionItem) { + switchedObject = ((StoreRegisterActionItem) set.leftSide).value; + } + //GraphPart switchLoc = part.nextParts.get(1).nextParts.get(0); + List caseBodyParts = new ArrayList<>(); + caseBodyParts.add(part.nextParts.get(0)); + GraphTargetItem top = null; + int cnt = 1; + while (part.nextParts.size() > 1 + && part.nextParts.get(1).getHeight() > 1 + && code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end) instanceof ActionIf + && ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) { + cnt++; + part = part.nextParts.get(1); + pos++; + caseBodyParts.add(part.nextParts.get(0)); + + set = (StrictEqActionItem) top; + caseValuesMap.put(pos, set.rightSide); + } + if (cnt == 1) { + stack.push(set); + } else { + part = part.nextParts.get(1); + + GraphPart defaultPart = part; //21-21 + //caseBodyParts.add(defaultPart); + + List defaultAndLastPart = new ArrayList<>(); + defaultAndLastPart.add(defaultPart); + defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1)); + + GraphPart defaultPart2 = getCommonPart(localData, defaultAndLastPart, loops);//34-37 + + List defaultCommands = new ArrayList<>(); + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(defaultPart2); + defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path); + + List loopContinues = new ArrayList<>(); + for (Loop l : loops) { + if (l.loopContinue != null) { + loopContinues.add(l.loopContinue); + } + } + + List breakParts = new ArrayList<>(); + /*for (int g = 0; g < caseBodyParts.size(); g++) { + if (g < caseBodyParts.size() - 1) { + if (caseBodyParts.get(g).leadsTo(code, caseBodyParts.get(g + 1), loops)) { + continue; + } + } + GraphPart nsp = caseBodyParts.get(g).getNextSuperPartPath(loopContinues); + if (nsp != null) { + breakParts.add(nsp); + } + } + Collections.sort(breakParts, new Comparator() { + @Override + public int compare(GraphPart o1, GraphPart o2) { + return o2.path.length() - o1.path.length(); + } + });*/ + + //GraphPart breakPart = breakParts.isEmpty() ? null : breakParts.get(0); + List mcp = new ArrayList<>(); + mcp.addAll(caseBodyParts); + if (defaultPart2 != null) { + mcp.add(defaultPart2); + } + GraphPart breakPart = getMostCommonPart(localData, mcp, loops); + if ((defaultPart2 != breakPart) && (defaultCommands.isEmpty())) { + defaultPart = defaultPart2; + } + + List caseValues = new ArrayList<>(); + for (int i = 0; i < caseBodyParts.size(); i++) { + if (caseValuesMap.containsKey(i)) { + caseValues.add(caseValuesMap.get(i)); + } else { + continue; + } + } + + List> caseCommands = new ArrayList<>(); + GraphPart next = null; + + next = breakPart; + + GraphTargetItem ti = checkLoop(next, stopPart, loops); + currentLoop = new Loop(loops.size(), null, next); + currentLoop.phase = 1; + loops.add(currentLoop); + //switchLoc.getNextPartPath(new ArrayList()); + List valuesMapping = new ArrayList<>(); + List caseBodies = new ArrayList<>(); + for (int i = 0; i < caseValues.size(); i++) { + GraphPart cur = caseBodyParts.get(i); + if (!caseBodies.contains(cur)) { + caseBodies.add(cur); + } + valuesMapping.add(caseBodies.indexOf(cur)); + } + + if (defaultPart == breakPart) { + defaultPart = null; + } + if ((defaultPart != null) && (defaultCommands.isEmpty())) { + List stopPart2x = new ArrayList<>(stopPart); + stopPart2x.add(next); + defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path); + } + + if (!defaultCommands.isEmpty()) { + if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) { + BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1); + if (bi.loopId == currentLoop.id) { + defaultCommands.remove(defaultCommands.size() - 1); + } + } + } + + List ignored = new ArrayList<>(); + for (Loop l : loops) { + ignored.add(l.loopContinue); + } + + for (int i = 0; i < caseBodies.size(); i++) { + List cc = new ArrayList<>(); + GraphPart nextCase = null; + nextCase = next; + if (next != null) { + if (i < caseBodies.size() - 1) { + if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) { + cc.add(new BreakItem(null, currentLoop.id)); + } else { + nextCase = caseBodies.get(i + 1); + } + } else if (!defaultCommands.isEmpty()) { + if (!caseBodies.get(i).leadsTo(localData, this, code, defaultPart, loops)) { + cc.add(new BreakItem(null, currentLoop.id)); + } else { + nextCase = defaultPart; + } + } + } + List stopPart2x = new ArrayList<>(stopPart); + //stopPart2.add(nextCase); + for (GraphPart b : caseBodies) { + if (b != caseBodies.get(i)) { + stopPart2x.add(b); + } + } + if (defaultPart != null) { + stopPart2x.add(defaultPart); + } + if (breakPart != null) { + stopPart2x.add(breakPart); + } + cc.addAll(0, printGraph(localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); + if (cc.size() >= 2) { + if (cc.get(cc.size() - 1) instanceof BreakItem) { + if ((cc.get(cc.size() - 2) instanceof ContinueItem) || (cc.get(cc.size() - 2) instanceof BreakItem)) { + cc.remove(cc.size() - 1); + } + } + } + caseCommands.add(cc); + } + ret = new ArrayList<>(); + ret.addAll(output); + SwitchItem sti = new SwitchItem(null, currentLoop, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping); + ret.add(sti); + currentLoop.phase = 2; + if (next != null) { + if (ti != null) { + ret.add(ti); + } else { + ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); + } + } + } + } + return ret; + } + + @Override + protected int checkIp(int ip) { + int oldIp = ip; + //return in for..in + GraphSourceItem action = code.get(ip); + if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { + if (ip + 3 < code.size()) { + if ((code.get(ip + 1) instanceof ActionEquals) || (code.get(ip + 1) instanceof ActionEquals2)) { + if (code.get(ip + 2) instanceof ActionNot) { + if (code.get(ip + 3) instanceof ActionIf) { + ActionIf aif = (ActionIf) code.get(ip + 3); + if (code.adr2pos(code.pos2adr(ip + 4) + aif.getJumpOffset()) == ip) { + ip += 4; + } + } + } + } + } + } + if (oldIp != ip) { + return checkIp(ip); + } + return ip; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java index 2c7bc5a5a..7f2a6a07a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -1,1011 +1,1011 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action; - -import com.jpexs.decompiler.flash.DisassemblyListener; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; -import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscatorSimple; -import com.jpexs.decompiler.flash.action.model.ConstantPool; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.special.ActionNop; -import com.jpexs.decompiler.flash.action.special.ActionStore; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.NotCompileTimeItem; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Scanner; -import java.util.TreeMap; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Class for reading data from SWF file - * - * @author JPEXS - */ -public class ActionListReader { - - private static final Logger logger = Logger.getLogger(ActionListReader.class.getName()); - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param sis - * @param version - * @param ip - * @param endIp - * @param path - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - * @throws java.util.concurrent.TimeoutException - */ - public static ActionList readActionListTimeout(final List listeners, final SWFInputStream sis, final int version, final int ip, final int endIp, final String path) throws IOException, InterruptedException, TimeoutException { - try { - final int deobfuscationMode = Configuration.autoDeobfuscate.get() ? Configuration.deobfuscationMode.get() : -1; - ActionList actions = CancellableWorker.call(new Callable() { - - @Override - public ActionList call() throws IOException, InterruptedException { - return readActionList(listeners, sis, version, ip, endIp, path, deobfuscationMode); - } - }, Configuration.decompilationTimeoutSingleMethod.get(), TimeUnit.SECONDS); - - return actions; - } catch (ExecutionException ex) { - Throwable cause = ex.getCause(); - if (cause instanceof InterruptedException) { - throw (InterruptedException) cause; - } else if (cause instanceof InterruptedException) { - throw (IOException) cause; - } else { - logger.log(Level.SEVERE, null, ex); - } - } - return new ActionList(); - } - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param sis - * @param version - * @param ip - * @param endIp - * @param path - * @param deobfuscationMode - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - */ - public static ActionList readActionList(List listeners, SWFInputStream sis, int version, int ip, int endIp, String path, int deobfuscationMode) throws IOException, InterruptedException { - // Map of the actions. Use TreeMap to sort the keys in ascending order - // actionMap and nextOffsets should contain exaclty the same keys - Map actionMap = new TreeMap<>(); - Map nextOffsets = new HashMap<>(); - Action entryAction = readActionListAtPos(listeners, null, - sis, actionMap, nextOffsets, - ip, 0, endIp, path, false, new ArrayList()); - - if (actionMap.isEmpty()) { - return new ActionList(); - } - - List addresses = new ArrayList<>(actionMap.keySet()); - - // add end action - Action lastAction = actionMap.get(addresses.get(addresses.size() - 1)); - long endAddress; - if (!(lastAction instanceof ActionEnd)) { - Action aEnd = new ActionEnd(); - aEnd.setAddress(nextOffsets.get(lastAction.getAddress())); - endAddress = aEnd.getAddress(); - actionMap.put(aEnd.getAddress(), aEnd); - nextOffsets.put(endAddress, endAddress + 1); - } - - ActionList actions = fixActionList(new ActionList(actionMap.values()), nextOffsets, version); - - // jump to the entry action when it is diffrent from the first action in the map - if (entryAction != actions.get(0)) { - ActionJump jump = new ActionDeobfuscateJump(0); - actions.addAction(0, jump); - jump.setJumpOffset((int) (entryAction.getAddress() - jump.getTotalActionLength())); - } - - if (SWFDecompilerPlugin.fireActionListParsed(actions, sis.getSwf())) { - actions = fixActionList(actions, null, version); - } - - if (deobfuscationMode == 0) { - try { - actions = deobfuscateActionList(listeners, actions, version, 0, path); - updateActionLengths(actions, version); - } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { - // keep orignal (not deobfuscated) actions - logger.log(Level.SEVERE, null, ex); - } - } else if (deobfuscationMode == 1) { - try { - new ActionDeobfuscatorSimple().actionListParsed(actions, sis.getSwf()); - new ActionDeobfuscator().actionListParsed(actions, sis.getSwf()); - } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { - // keep orignal (not deobfuscated) actions - logger.log(Level.SEVERE, null, ex); - } - } - - return actions; - } - - public static ActionList fixActionList(ActionList actions, Map nextOffsets, int version) { - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - ActionList ret = new ActionList(); - - if (nextOffsets != null) { - int index = 0; - while (index != -1 && index < actions.size()) { - Action action = actions.get(index); - ret.add(action); - index++; - if (index < actions.size()) { - long nextAddress = nextOffsets.get(action.getAddress()); - if (actions.get(index).getAddress() != nextAddress) { - if (!action.isExit() && !(action instanceof ActionJump)) { - ActionJump jump = new ActionDeobfuscateJump(0); - jump.setAddress(action.getAddress()); - int size = jump.getTotalActionLength(); - jump.setJumpOffset((int) (nextAddress - action.getAddress() - size)); - ret.add(jump); - } - } - } - } - } else { - ret.addAll(actions); - } - - // Map for storing the targers of the "jump" actions - // "jump" action can be ActionIf, ActionJump and any ActionStore - Map jumps = new HashMap<>(); - getJumps(ret, jumps); - - updateActionLengths(ret, version); - updateAddresses(ret, 0); - long endAddress = ret.get(ret.size() - 1).getAddress(); - - updateJumps(ret, jumps, containerLastActions, endAddress); - updateActionStores(ret, jumps); - updateContainerSizes(ret, containerLastActions); - - return ret; - } - - public static List getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException { - // Map of the actions. Use TreeMap to sort the keys in ascending order - Map actionMap = new TreeMap<>(); - Map nextOffsets = new HashMap<>(); - readActionListAtPos(new ArrayList(), null, - sis, actionMap, nextOffsets, - startIp, startIp, endIp + 1, "", false, new ArrayList()); - - return new ArrayList<>(actionMap.values()); - } - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param actions - * @param version - * @param ip - * @param path - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - */ - private static ActionList deobfuscateActionList(List listeners, ActionList actions, int version, int ip, String path) throws IOException, InterruptedException { - if (actions.isEmpty()) { - return actions; - } - - Action lastAction = actions.get(actions.size() - 1); - int endIp = (int) lastAction.getAddress(); - - List retMap = new ArrayList<>(endIp); - for (int i = 0; i < endIp; i++) { - retMap.add(null); - } - List actionMap = new ArrayList<>(endIp); - for (int i = 0; i <= endIp; i++) { - actionMap.add(null); - } - for (Action a : actions) { - actionMap.set((int) a.getAddress(), a); - } - - int maxRecursionLevel = 0; - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) { - maxRecursionLevel++; - } - if (a instanceof ActionIf) { - ActionIf aif = (ActionIf) a; - aif.ignoreUsed = false; - aif.jumpUsed = false; - } - } - - deobfustaceActionListAtPosRecursive(listeners, - new ArrayList(), - new HashMap>(), - new ActionLocalData(), - new TranslateStack(), - new ConstantPool(), - actionMap, ip, retMap, ip, endIp, path, - new HashMap(), false, - new HashMap>(), - version, 0, maxRecursionLevel); - - ActionList ret = new ActionList(); - Action last = null; - for (Action a : retMap) { - if (a != last && a != null) { - ret.add(a); - } - last = a; - } - ret.removeNops(); - ActionList reta = new ActionList(); - for (Object o : ret) { - if (o instanceof Action) { - reta.add((Action) o); - } - } - return reta; - } - - private static long getNearAddress(ActionList actions, long address, boolean next) { - int min = 0; - int max = actions.size() - 1; - - while (max >= min) { - int mid = (min + max) / 2; - long midValue = actions.get(mid).getAddress(); - if (midValue == address) { - return address; - } else if (midValue < address) { - min = mid + 1; - } else { - max = mid - 1; - } - } - - return next - ? (min < actions.size() ? actions.get(min).getAddress() : -1) - : (max >= 0 ? actions.get(max).getAddress() : -1); - } - - private static Map actionListToMap(List actions) { - Map map = new HashMap<>(actions.size()); - for (Action a : actions) { - long address = a.getAddress(); - // There are multiple actions in the same address (2nd action is a jump for obfuscated code) - // So this check is required - if (!map.containsKey(address)) { - map.put(a.getAddress(), a); - } - } - return map; - } - - private static void getJumps(List actions, Map jumps) { - Map actionMap = actionListToMap(actions); - for (Action a : actions) { - long target = -1; - if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - target = aIf.getAddress() + a.getTotalActionLength() + aIf.getJumpOffset(); - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - target = aJump.getAddress() + a.getTotalActionLength() + aJump.getJumpOffset(); - } else if (a instanceof ActionStore) { - ActionStore aStore = (ActionStore) a; - int storeSize = aStore.getStoreSize(); - // skip storeSize + 1 actions (+1 is the current action) - Action targetAction = a; - for (int i = 0; i <= storeSize; i++) { - long address = targetAction.getAddress() + targetAction.getTotalActionLength(); - targetAction = actionMap.get(address); - if (targetAction == null) { - break; - } - } - jumps.put(a, targetAction); - } - if (target >= 0) { - Action targetAction = actionMap.get(target); - jumps.put(a, targetAction); - } - } - } - - public static List getContainerLastActions(ActionList actions, Action action) { - GraphSourceItemContainer container = (GraphSourceItemContainer) action; - List sizes = container.getContainerSizes(); - long endAddress = action.getAddress() + container.getHeaderSize(); - List lasts = new ArrayList<>(sizes.size()); - for (long size : sizes) { - endAddress += size; - long lastActionAddress = getNearAddress(actions, endAddress - 1, false); - Action lastAction = null; - if (lastActionAddress != -1) { - lastAction = actions.getByAddress(lastActionAddress); - } - lasts.add(lastAction); - } - return lasts; - } - - private static void getContainerLastActions(ActionList actions, Map> lastActions) { - for (Action a : actions) { - if (a instanceof GraphSourceItemContainer) { - lastActions.put(a, getContainerLastActions(actions, a)); - } - } - } - - private static long updateAddresses(List actions, long address) { - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - a.setAddress(address); - int length = a.getTotalActionLength(); - if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { - // placeholder for jump action - length = new ActionDeobfuscateJump(0).getTotalActionLength(); - } - address += length; - } - return address; - } - - private static void updateActionLengths(List actions, int version) { - for (int i = 0; i < actions.size(); i++) { - actions.get(i).updateLength(version); - } - } - - private static void updateActionStores(List actions, Map jumps) { - Map actionMap = actionListToMap(actions); - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof ActionStore) { - ActionStore aStore = (ActionStore) a; - Action nextActionAfterStore = jumps.get(a); - Action a1 = a; - List store = new ArrayList<>(); - while (true) { - long address = a1.getAddress() + a1.getTotalActionLength(); - a1 = actionMap.get(address); - if (a1 == null || a1 == nextActionAfterStore) { - break; - } - store.add(a1); - } - aStore.setStore(store); - } - } - } - - private static void updateContainerSizes(List actions, Map> containerLastActions) { - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer container = (GraphSourceItemContainer) a; - List lastActions = containerLastActions.get(a); - long startAddress = a.getAddress() + container.getHeaderSize(); - for (int j = 0; j < lastActions.size(); j++) { - Action lastAction = lastActions.get(j); - int length = (int) (lastAction.getAddress() + lastAction.getTotalActionLength() - startAddress); - container.setContainerSize(j, length); - startAddress += length; - } - } - } - } - - private static void replaceJumpTargets(Map jumps, Action oldTarget, Action newTarget) { - for (Action a : jumps.keySet()) { - if (jumps.get(a) == oldTarget) { - jumps.put(a, newTarget); - } - } - } - - private static void replaceContainerLastActions(Map> containerLastActions, Action oldTarget, Action newTarget) { - for (Action a : containerLastActions.keySet()) { - List targets = containerLastActions.get(a); - for (int i = 0; i < targets.size(); i++) { - if (targets.get(i) == oldTarget) { - targets.set(i, newTarget); - } - } - } - } - - private static void updateJumps(List actions, Map jumps, Map> containerLastActions, long endAddress) { - if (actions.isEmpty()) { - return; - } - - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { - ActionJump aJump = new ActionDeobfuscateJump(0); - aJump.setJumpOffset((int) (endAddress - a.getAddress() - aJump.getTotalActionLength())); - aJump.setAddress(a.getAddress()); - replaceJumpTargets(jumps, a, aJump); - replaceContainerLastActions(containerLastActions, a, aJump); - a = aJump; - actions.set(i, a); - } else if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - Action target = jumps.get(a); - long offset; - if (target != null) { - offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); - } else { - offset = endAddress - a.getAddress() - a.getTotalActionLength(); - } - aIf.setJumpOffset((int) offset); - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - Action target = jumps.get(a); - long offset; - if (target != null) { - offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); - } else { - offset = endAddress - a.getAddress() - a.getTotalActionLength(); - } - aJump.setJumpOffset((int) offset); - } - } - } - - /** - * Removes an action from the action list, and updates all references This - * method will keep the inner actions of the container when you remove the - * container - * - * @param actions - * @param index - * @param version - * @param removeWhenLast - * @return - */ - public static boolean removeAction(ActionList actions, int index, int version, boolean removeWhenLast) { - - if (index < 0 || actions.size() <= index) { - return false; - } - - long startIp = actions.get(0).getAddress(); - Action lastAction = actions.get(actions.size() - 1); - long endAddress = lastAction.getAddress() + lastAction.getTotalActionLength(); - - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - Map jumps = new HashMap<>(); - getJumps(actions, jumps); - - Action prevAction = index > 0 ? actions.get(index - 1) : null; - Action nextAction = index + 1 < actions.size() ? actions.get(index + 1) : null; - Action actionToRemove = actions.get(index); - for (Action a : containerLastActions.keySet()) { - List lastActions = containerLastActions.get(a); - for (int i = 0; i < lastActions.size(); i++) { - if (lastActions.get(i) == actionToRemove) { - if (!removeWhenLast) { - return false; - } - lastActions.set(i, prevAction); - } - } - } - for (Action a : jumps.keySet()) { - Action targetAction = jumps.get(a); - if (targetAction == actionToRemove) { - jumps.put(a, nextAction); - } - } - if (containerLastActions.containsKey(actionToRemove)) { - containerLastActions.remove(actionToRemove); - } - if (jumps.containsKey(actionToRemove)) { - jumps.remove(actionToRemove); - } - - actions.remove(index); - - updateActionLengths(actions, version); - updateAddresses(actions, startIp); - updateJumps(actions, jumps, containerLastActions, endAddress); - updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); - - return true; - } - - /** - * Adds an action to the action list to the specified location, and updates - * all references - * - * @param actions - * @param index - * @param action - * @param version - * @param addToContainer - * @param replaceJump - * @return - */ - public static boolean addAction(ActionList actions, int index, Action action, - int version, boolean addToContainer, boolean replaceJump) { - - if (index < 0 || actions.size() < index) { - return false; - } - - long startIp = actions.get(0).getAddress(); - Action lastAction = actions.get(actions.size() - 1); - if (!(lastAction instanceof ActionEnd)) { - Action aEnd = new ActionEnd(); - aEnd.setAddress(lastAction.getAddress() + lastAction.getTotalActionLength()); - actions.add(aEnd); - lastAction = aEnd; - } - - long endAddress = lastAction.getAddress(); - - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - Map jumps = new HashMap<>(); - List tempActions = new ArrayList<>(actions); - tempActions.add(action); - getJumps(tempActions, jumps); - - Action prevAction = actions.get(index); - if (addToContainer) { - for (Action a : containerLastActions.keySet()) { - List lastActions = containerLastActions.get(a); - for (int i = 0; i < lastActions.size(); i++) { - if (lastActions.get(i) == prevAction) { - lastActions.set(i, action); - } - } - } - } - - if (replaceJump) { - for (Action a : jumps.keySet()) { - Action targetAction = jumps.get(a); - if (targetAction == prevAction) { - jumps.put(a, action); - } - } - } - - actions.add(index, action); - - updateActionLengths(actions, version); - updateAddresses(actions, startIp); - updateJumps(actions, jumps, containerLastActions, endAddress); - updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); - - return true; - } - - private static Action readActionListAtPos(List listeners, ConstantPool cpool, - SWFInputStream sis, Map actions, Map nextOffsets, - long ip, long startIp, long endIp, String path, boolean indeterminate, List visitedContainers) throws IOException { - - Action entryAction = null; - - if (visitedContainers.contains(ip)) { - return null; - } - visitedContainers.add(ip); - - Queue jumpQueue = new LinkedList<>(); - jumpQueue.add(ip); - while (!jumpQueue.isEmpty()) { - ip = jumpQueue.remove(); - if (ip < startIp) { - continue; - } - - while (endIp == -1 || endIp > ip) { - sis.seek((int) ip); - - Action a; - if ((a = sis.readAction()) == null) { - break; - } - - int actionLengthWithHeader = a.getTotalActionLength(); - - // unknown action, replace with jump - if (a instanceof ActionNop) { - ActionJump aJump = new ActionDeobfuscateJump(0); - int jumpLength = aJump.getTotalActionLength(); - aJump.setAddress(a.getAddress()); - aJump.setJumpOffset(actionLengthWithHeader - jumpLength); - a = aJump; - actionLengthWithHeader = a.getTotalActionLength(); - } - - if (entryAction == null) { - entryAction = a; - } - - Action existingAction = actions.get(ip); - if (existingAction != null) { - break; - } - - actions.put(ip, a); - nextOffsets.put(ip, ip + actionLengthWithHeader); - - long pos = sis.getPos(); - long length = pos + sis.available(); - for (int i = 0; i < listeners.size(); i++) { - listeners.get(i).progressReading(pos, length); - } - - a.setAddress(ip); - - if (a instanceof ActionPush && cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } else if (a instanceof ActionConstantPool) { - cpool = new ConstantPool(((ActionConstantPool) a).constantPool); - } else if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - long nIp = ip + actionLengthWithHeader + aIf.getJumpOffset(); - if (nIp >= 0) { - jumpQueue.add(nIp); - } - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - long nIp = ip + actionLengthWithHeader + aJump.getJumpOffset(); - if (nIp >= 0) { - jumpQueue.add(nIp); - } - break; - } else if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - String cntName = cnt.getName(); - String newPath = path + (cntName == null ? "" : "/" + cntName); - for (long size : cnt.getContainerSizes()) { - if (size != 0) { - long ip2 = ip + actionLengthWithHeader; - long endIp2 = ip + actionLengthWithHeader + size; - readActionListAtPos(listeners, cpool, - sis, actions, nextOffsets, - ip2, startIp, endIp2, newPath, indeterminate, visitedContainers); - actionLengthWithHeader += size; - } - } - } - - ip += actionLengthWithHeader; - - if (a.isExit()) { - break; - } - } - } - return entryAction; - } - - private static void deobfustaceActionListAtPosRecursive(List listeners, List output, HashMap> containers, ActionLocalData localData, TranslateStack stack, ConstantPool cpool, List actions, int ip, List ret, int startIp, int endip, String path, Map visited, boolean indeterminate, Map> decisionStates, int version, int recursionLevel, int maxRecursionLevel) throws IOException, InterruptedException { - boolean debugMode = false; - boolean decideBranch = false; - - if (recursionLevel > maxRecursionLevel + 1) { - throw new TranslateException("deobfustaceActionListAtPosRecursive max recursion level reached."); - } - - Action a; - Scanner sc = null; - loopip: - while (((endip == -1) || (endip > ip)) && (a = actions.get(ip)) != null) { - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException(); - } - - int actionLen = a.getTotalActionLength(); - if (!visited.containsKey(ip)) { - visited.put(ip, 0); - } - int curVisited = visited.get(ip); - curVisited++; - visited.put(ip, curVisited); - for (int i = 0; i < listeners.size(); i++) { - listeners.get(i).progressDeobfuscating(ip, actions.size()); - } - int info = a.getTotalActionLength(); - - if (a instanceof ActionPush) { - if (cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } - } - - if (debugMode) { - String atos = a.getASMSource(new ActionList(), new HashSet(), ScriptExportMode.PCODE); - if (a instanceof GraphSourceItemContainer) { - atos = a.toString(); - } - System.err.println("readActionListAtPos ip: " + (ip - startIp) + " (0x" + Helper.formatAddress(ip - startIp) + ") " + " action(len " + a.actionLength + "): " + atos + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Helper.stackToString(stack, LocalData.create(cpool)) + " " + Helper.byteArrToString(a.getBytes(version))); - System.err.print("variables: "); - for (Map.Entry v : localData.variables.entrySet()) { - System.err.print("'" + v + "' = " + v.getValue().toString(LocalData.create(cpool)) + ", "); - } - System.err.println(); - String add = ""; - if (a instanceof ActionIf) { - add = " change: " + ((ActionIf) a).getJumpOffset(); - } - if (a instanceof ActionJump) { - add = " change: " + ((ActionJump) a).getJumpOffset(); - } - System.err.println(add); - } - - int newip = -1; - - if (a instanceof ActionConstantPool) { - if (cpool == null) { - cpool = new ConstantPool(); - } - cpool.setNew(((ActionConstantPool) a).constantPool); - } - ActionIf aif = null; - boolean goaif = false; - if (!a.isIgnored()) { - String varname = null; - if (a instanceof StoreTypeAction) { - StoreTypeAction sta = (StoreTypeAction) a; - varname = sta.getVariableName(stack, cpool); - } - - try { - if (a instanceof ActionIf) { - aif = (ActionIf) a; - - GraphTargetItem top = stack.pop(); - int nip = ip + actionLen + aif.getJumpOffset(); - - if (decideBranch) { - System.out.print("newip " + nip + ", "); - System.out.print("Action: jump(j),ignore(i),compute(c)?"); - if (sc == null) { - sc = new Scanner(System.in); - } - String next = sc.next(); - switch (next) { - case "j": - newip = nip; - break; - case "i": - break; - case "c": - goaif = true; - break; - } - } else if (top.isCompileTime() && (!top.hasSideEffect())) { - if (debugMode) { - System.err.print("is compiletime -> "); - } - if (EcmaScript.toBoolean(top.getResult())) { - newip = nip; - aif.jumpUsed = true; - if (debugMode) { - System.err.println("jump"); - } - } else { - aif.ignoreUsed = true; - if (debugMode) { - System.err.println("ignore"); - } - } - } else { - if (debugMode) { - System.err.println("goaif"); - } - goaif = true; - } - } else if (a instanceof ActionJump) { - newip = ip + actionLen + ((ActionJump) a).getJumpOffset(); - } else if (!(a instanceof GraphSourceItemContainer)) { - //return in for..in, TODO:Handle this better way - if (((a instanceof ActionEquals) || (a instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) { - stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList<>())); - } - if ((a instanceof ActionStoreRegister) && stack.isEmpty()) { - stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList<>())); - } - a.translate(localData, stack, output, Graph.SOP_USE_STATIC/*Graph.SOP_SKIP_STATIC*/, path); - } - } catch (RuntimeException ex) { - logger.log(Level.SEVERE, "Disassembly exception", ex); - break; - } - - HashMap vars = localData.variables; - if (varname != null) { - GraphTargetItem varval = vars.get(varname); - if (varval != null && varval.isCompileTime() && indeterminate) { - vars.put(varname, new NotCompileTimeItem(null, varval)); - } - } - } - for (int i = 0; i < actionLen; i++) { - ret.set(ip + i, a); - } - - if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - if (a instanceof Action) { - long endAddr = a.getAddress() + cnt.getHeaderSize(); - String cntName = cnt.getName(); - List> output2s = new ArrayList<>(); - for (long size : cnt.getContainerSizes()) { - if (size == 0) { - output2s.add(new ArrayList()); - continue; - } - ActionLocalData localData2; - List output2 = new ArrayList<>(); - if ((cnt instanceof ActionDefineFunction) || (cnt instanceof ActionDefineFunction2)) { - localData2 = new ActionLocalData(); - } else { - localData2 = localData; - } - deobfustaceActionListAtPosRecursive(listeners, output2, containers, localData2, new TranslateStack(), cpool, actions, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); - output2s.add(output2); - endAddr += size; - } - cnt.translateContainer(output2s, stack, output, localData.regNames, localData.variables, localData.functions); - ip = (int) endAddr; - continue; - } - } - - if (a instanceof ActionEnd) { - break; - } - if (goaif) { - aif.ignoreUsed = true; - aif.jumpUsed = true; - indeterminate = true; - - HashMap vars = localData.variables; - boolean stateChanged = false; - if (decisionStates.containsKey(ip)) { - HashMap oldstate = decisionStates.get(ip); - if (oldstate.size() != vars.size()) { - stateChanged = true; - } else { - for (String k : vars.keySet()) { - if (!oldstate.containsKey(k)) { - stateChanged = true; - break; - } - if (!vars.get(k).isCompileTime() && oldstate.get(k).isCompileTime()) { - stateChanged = true; - break; - } - } - } - } - HashMap curstate = new HashMap<>(); - curstate.putAll(vars); - decisionStates.put(ip, curstate); - - if ((!stateChanged) && curVisited > 1) { - List branches = new ArrayList<>(); - branches.add(ip + actionLen + aif.getJumpOffset()); - branches.add(ip + actionLen); - for (int br : branches) { - int visc = 0; - if (visited.containsKey(br)) { - visc = visited.get(br); - } - if (visc == 0) {//(localData.regNames), - new HashMap<>(localData.variables), new HashMap<>(localData.functions)); - deobfustaceActionListAtPosRecursive(listeners, output, containers, subLocalData, subStack, cpool, actions, ip + actionLen + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); - } - - if (newip > -1) { - ip = newip; - } else { - ip += info; - } - - if (a.isExit()) { - break; - } - } - for (DisassemblyListener listener : listeners) { - listener.progressDeobfuscating(ip, actions.size()); - } - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscatorSimple; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionNop; +import com.jpexs.decompiler.flash.action.special.ActionStore; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.NotCompileTimeItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Scanner; +import java.util.TreeMap; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Class for reading data from SWF file + * + * @author JPEXS + */ +public class ActionListReader { + + private static final Logger logger = Logger.getLogger(ActionListReader.class.getName()); + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param sis + * @param version + * @param ip + * @param endIp + * @param path + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + * @throws java.util.concurrent.TimeoutException + */ + public static ActionList readActionListTimeout(final List listeners, final SWFInputStream sis, final int version, final int ip, final int endIp, final String path) throws IOException, InterruptedException, TimeoutException { + try { + final int deobfuscationMode = Configuration.autoDeobfuscate.get() ? Configuration.deobfuscationMode.get() : -1; + ActionList actions = CancellableWorker.call(new Callable() { + + @Override + public ActionList call() throws IOException, InterruptedException { + return readActionList(listeners, sis, version, ip, endIp, path, deobfuscationMode); + } + }, Configuration.decompilationTimeoutSingleMethod.get(), TimeUnit.SECONDS); + + return actions; + } catch (ExecutionException ex) { + Throwable cause = ex.getCause(); + if (cause instanceof InterruptedException) { + throw (InterruptedException) cause; + } else if (cause instanceof InterruptedException) { + throw (IOException) cause; + } else { + logger.log(Level.SEVERE, null, ex); + } + } + return new ActionList(); + } + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param sis + * @param version + * @param ip + * @param endIp + * @param path + * @param deobfuscationMode + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + */ + public static ActionList readActionList(List listeners, SWFInputStream sis, int version, int ip, int endIp, String path, int deobfuscationMode) throws IOException, InterruptedException { + // Map of the actions. Use TreeMap to sort the keys in ascending order + // actionMap and nextOffsets should contain exaclty the same keys + Map actionMap = new TreeMap<>(); + Map nextOffsets = new HashMap<>(); + Action entryAction = readActionListAtPos(listeners, null, + sis, actionMap, nextOffsets, + ip, 0, endIp, path, false, new ArrayList()); + + if (actionMap.isEmpty()) { + return new ActionList(); + } + + List addresses = new ArrayList<>(actionMap.keySet()); + + // add end action + Action lastAction = actionMap.get(addresses.get(addresses.size() - 1)); + long endAddress; + if (!(lastAction instanceof ActionEnd)) { + Action aEnd = new ActionEnd(); + aEnd.setAddress(nextOffsets.get(lastAction.getAddress())); + endAddress = aEnd.getAddress(); + actionMap.put(aEnd.getAddress(), aEnd); + nextOffsets.put(endAddress, endAddress + 1); + } + + ActionList actions = fixActionList(new ActionList(actionMap.values()), nextOffsets, version); + + // jump to the entry action when it is diffrent from the first action in the map + if (entryAction != actions.get(0)) { + ActionJump jump = new ActionDeobfuscateJump(0); + actions.addAction(0, jump); + jump.setJumpOffset((int) (entryAction.getAddress() - jump.getTotalActionLength())); + } + + if (SWFDecompilerPlugin.fireActionListParsed(actions, sis.getSwf())) { + actions = fixActionList(actions, null, version); + } + + if (deobfuscationMode == 0) { + try { + actions = deobfuscateActionList(listeners, actions, version, 0, path); + updateActionLengths(actions, version); + } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { + // keep orignal (not deobfuscated) actions + logger.log(Level.SEVERE, null, ex); + } + } else if (deobfuscationMode == 1) { + try { + new ActionDeobfuscatorSimple().actionListParsed(actions, sis.getSwf()); + new ActionDeobfuscator().actionListParsed(actions, sis.getSwf()); + } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { + // keep orignal (not deobfuscated) actions + logger.log(Level.SEVERE, null, ex); + } + } + + return actions; + } + + public static ActionList fixActionList(ActionList actions, Map nextOffsets, int version) { + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + ActionList ret = new ActionList(); + + if (nextOffsets != null) { + int index = 0; + while (index != -1 && index < actions.size()) { + Action action = actions.get(index); + ret.add(action); + index++; + if (index < actions.size()) { + long nextAddress = nextOffsets.get(action.getAddress()); + if (actions.get(index).getAddress() != nextAddress) { + if (!action.isExit() && !(action instanceof ActionJump)) { + ActionJump jump = new ActionDeobfuscateJump(0); + jump.setAddress(action.getAddress()); + int size = jump.getTotalActionLength(); + jump.setJumpOffset((int) (nextAddress - action.getAddress() - size)); + ret.add(jump); + } + } + } + } + } else { + ret.addAll(actions); + } + + // Map for storing the targers of the "jump" actions + // "jump" action can be ActionIf, ActionJump and any ActionStore + Map jumps = new HashMap<>(); + getJumps(ret, jumps); + + updateActionLengths(ret, version); + updateAddresses(ret, 0); + long endAddress = ret.get(ret.size() - 1).getAddress(); + + updateJumps(ret, jumps, containerLastActions, endAddress); + updateActionStores(ret, jumps); + updateContainerSizes(ret, containerLastActions); + + return ret; + } + + public static List getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException { + // Map of the actions. Use TreeMap to sort the keys in ascending order + Map actionMap = new TreeMap<>(); + Map nextOffsets = new HashMap<>(); + readActionListAtPos(new ArrayList(), null, + sis, actionMap, nextOffsets, + startIp, startIp, endIp + 1, "", false, new ArrayList()); + + return new ArrayList<>(actionMap.values()); + } + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param actions + * @param version + * @param ip + * @param path + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + */ + private static ActionList deobfuscateActionList(List listeners, ActionList actions, int version, int ip, String path) throws IOException, InterruptedException { + if (actions.isEmpty()) { + return actions; + } + + Action lastAction = actions.get(actions.size() - 1); + int endIp = (int) lastAction.getAddress(); + + List retMap = new ArrayList<>(endIp); + for (int i = 0; i < endIp; i++) { + retMap.add(null); + } + List actionMap = new ArrayList<>(endIp); + for (int i = 0; i <= endIp; i++) { + actionMap.add(null); + } + for (Action a : actions) { + actionMap.set((int) a.getAddress(), a); + } + + int maxRecursionLevel = 0; + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) { + maxRecursionLevel++; + } + if (a instanceof ActionIf) { + ActionIf aif = (ActionIf) a; + aif.ignoreUsed = false; + aif.jumpUsed = false; + } + } + + deobfustaceActionListAtPosRecursive(listeners, + new ArrayList(), + new HashMap>(), + new ActionLocalData(), + new TranslateStack(path), + new ConstantPool(), + actionMap, ip, retMap, ip, endIp, path, + new HashMap(), false, + new HashMap>(), + version, 0, maxRecursionLevel); + + ActionList ret = new ActionList(); + Action last = null; + for (Action a : retMap) { + if (a != last && a != null) { + ret.add(a); + } + last = a; + } + ret.removeNops(); + ActionList reta = new ActionList(); + for (Object o : ret) { + if (o instanceof Action) { + reta.add((Action) o); + } + } + return reta; + } + + private static long getNearAddress(ActionList actions, long address, boolean next) { + int min = 0; + int max = actions.size() - 1; + + while (max >= min) { + int mid = (min + max) / 2; + long midValue = actions.get(mid).getAddress(); + if (midValue == address) { + return address; + } else if (midValue < address) { + min = mid + 1; + } else { + max = mid - 1; + } + } + + return next + ? (min < actions.size() ? actions.get(min).getAddress() : -1) + : (max >= 0 ? actions.get(max).getAddress() : -1); + } + + private static Map actionListToMap(List actions) { + Map map = new HashMap<>(actions.size()); + for (Action a : actions) { + long address = a.getAddress(); + // There are multiple actions in the same address (2nd action is a jump for obfuscated code) + // So this check is required + if (!map.containsKey(address)) { + map.put(a.getAddress(), a); + } + } + return map; + } + + private static void getJumps(List actions, Map jumps) { + Map actionMap = actionListToMap(actions); + for (Action a : actions) { + long target = -1; + if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + target = aIf.getAddress() + a.getTotalActionLength() + aIf.getJumpOffset(); + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + target = aJump.getAddress() + a.getTotalActionLength() + aJump.getJumpOffset(); + } else if (a instanceof ActionStore) { + ActionStore aStore = (ActionStore) a; + int storeSize = aStore.getStoreSize(); + // skip storeSize + 1 actions (+1 is the current action) + Action targetAction = a; + for (int i = 0; i <= storeSize; i++) { + long address = targetAction.getAddress() + targetAction.getTotalActionLength(); + targetAction = actionMap.get(address); + if (targetAction == null) { + break; + } + } + jumps.put(a, targetAction); + } + if (target >= 0) { + Action targetAction = actionMap.get(target); + jumps.put(a, targetAction); + } + } + } + + public static List getContainerLastActions(ActionList actions, Action action) { + GraphSourceItemContainer container = (GraphSourceItemContainer) action; + List sizes = container.getContainerSizes(); + long endAddress = action.getAddress() + container.getHeaderSize(); + List lasts = new ArrayList<>(sizes.size()); + for (long size : sizes) { + endAddress += size; + long lastActionAddress = getNearAddress(actions, endAddress - 1, false); + Action lastAction = null; + if (lastActionAddress != -1) { + lastAction = actions.getByAddress(lastActionAddress); + } + lasts.add(lastAction); + } + return lasts; + } + + private static void getContainerLastActions(ActionList actions, Map> lastActions) { + for (Action a : actions) { + if (a instanceof GraphSourceItemContainer) { + lastActions.put(a, getContainerLastActions(actions, a)); + } + } + } + + private static long updateAddresses(List actions, long address) { + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + a.setAddress(address); + int length = a.getTotalActionLength(); + if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { + // placeholder for jump action + length = new ActionDeobfuscateJump(0).getTotalActionLength(); + } + address += length; + } + return address; + } + + private static void updateActionLengths(List actions, int version) { + for (int i = 0; i < actions.size(); i++) { + actions.get(i).updateLength(version); + } + } + + private static void updateActionStores(List actions, Map jumps) { + Map actionMap = actionListToMap(actions); + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof ActionStore) { + ActionStore aStore = (ActionStore) a; + Action nextActionAfterStore = jumps.get(a); + Action a1 = a; + List store = new ArrayList<>(); + while (true) { + long address = a1.getAddress() + a1.getTotalActionLength(); + a1 = actionMap.get(address); + if (a1 == null || a1 == nextActionAfterStore) { + break; + } + store.add(a1); + } + aStore.setStore(store); + } + } + } + + private static void updateContainerSizes(List actions, Map> containerLastActions) { + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer container = (GraphSourceItemContainer) a; + List lastActions = containerLastActions.get(a); + long startAddress = a.getAddress() + container.getHeaderSize(); + for (int j = 0; j < lastActions.size(); j++) { + Action lastAction = lastActions.get(j); + int length = (int) (lastAction.getAddress() + lastAction.getTotalActionLength() - startAddress); + container.setContainerSize(j, length); + startAddress += length; + } + } + } + } + + private static void replaceJumpTargets(Map jumps, Action oldTarget, Action newTarget) { + for (Action a : jumps.keySet()) { + if (jumps.get(a) == oldTarget) { + jumps.put(a, newTarget); + } + } + } + + private static void replaceContainerLastActions(Map> containerLastActions, Action oldTarget, Action newTarget) { + for (Action a : containerLastActions.keySet()) { + List targets = containerLastActions.get(a); + for (int i = 0; i < targets.size(); i++) { + if (targets.get(i) == oldTarget) { + targets.set(i, newTarget); + } + } + } + } + + private static void updateJumps(List actions, Map jumps, Map> containerLastActions, long endAddress) { + if (actions.isEmpty()) { + return; + } + + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { + ActionJump aJump = new ActionDeobfuscateJump(0); + aJump.setJumpOffset((int) (endAddress - a.getAddress() - aJump.getTotalActionLength())); + aJump.setAddress(a.getAddress()); + replaceJumpTargets(jumps, a, aJump); + replaceContainerLastActions(containerLastActions, a, aJump); + a = aJump; + actions.set(i, a); + } else if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + Action target = jumps.get(a); + long offset; + if (target != null) { + offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); + } else { + offset = endAddress - a.getAddress() - a.getTotalActionLength(); + } + aIf.setJumpOffset((int) offset); + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + Action target = jumps.get(a); + long offset; + if (target != null) { + offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); + } else { + offset = endAddress - a.getAddress() - a.getTotalActionLength(); + } + aJump.setJumpOffset((int) offset); + } + } + } + + /** + * Removes an action from the action list, and updates all references This + * method will keep the inner actions of the container when you remove the + * container + * + * @param actions + * @param index + * @param version + * @param removeWhenLast + * @return + */ + public static boolean removeAction(ActionList actions, int index, int version, boolean removeWhenLast) { + + if (index < 0 || actions.size() <= index) { + return false; + } + + long startIp = actions.get(0).getAddress(); + Action lastAction = actions.get(actions.size() - 1); + long endAddress = lastAction.getAddress() + lastAction.getTotalActionLength(); + + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + Map jumps = new HashMap<>(); + getJumps(actions, jumps); + + Action prevAction = index > 0 ? actions.get(index - 1) : null; + Action nextAction = index + 1 < actions.size() ? actions.get(index + 1) : null; + Action actionToRemove = actions.get(index); + for (Action a : containerLastActions.keySet()) { + List lastActions = containerLastActions.get(a); + for (int i = 0; i < lastActions.size(); i++) { + if (lastActions.get(i) == actionToRemove) { + if (!removeWhenLast) { + return false; + } + lastActions.set(i, prevAction); + } + } + } + for (Action a : jumps.keySet()) { + Action targetAction = jumps.get(a); + if (targetAction == actionToRemove) { + jumps.put(a, nextAction); + } + } + if (containerLastActions.containsKey(actionToRemove)) { + containerLastActions.remove(actionToRemove); + } + if (jumps.containsKey(actionToRemove)) { + jumps.remove(actionToRemove); + } + + actions.remove(index); + + updateActionLengths(actions, version); + updateAddresses(actions, startIp); + updateJumps(actions, jumps, containerLastActions, endAddress); + updateActionStores(actions, jumps); + updateContainerSizes(actions, containerLastActions); + + return true; + } + + /** + * Adds an action to the action list to the specified location, and updates + * all references + * + * @param actions + * @param index + * @param action + * @param version + * @param addToContainer + * @param replaceJump + * @return + */ + public static boolean addAction(ActionList actions, int index, Action action, + int version, boolean addToContainer, boolean replaceJump) { + + if (index < 0 || actions.size() < index) { + return false; + } + + long startIp = actions.get(0).getAddress(); + Action lastAction = actions.get(actions.size() - 1); + if (!(lastAction instanceof ActionEnd)) { + Action aEnd = new ActionEnd(); + aEnd.setAddress(lastAction.getAddress() + lastAction.getTotalActionLength()); + actions.add(aEnd); + lastAction = aEnd; + } + + long endAddress = lastAction.getAddress(); + + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + Map jumps = new HashMap<>(); + List tempActions = new ArrayList<>(actions); + tempActions.add(action); + getJumps(tempActions, jumps); + + Action prevAction = actions.get(index); + if (addToContainer) { + for (Action a : containerLastActions.keySet()) { + List lastActions = containerLastActions.get(a); + for (int i = 0; i < lastActions.size(); i++) { + if (lastActions.get(i) == prevAction) { + lastActions.set(i, action); + } + } + } + } + + if (replaceJump) { + for (Action a : jumps.keySet()) { + Action targetAction = jumps.get(a); + if (targetAction == prevAction) { + jumps.put(a, action); + } + } + } + + actions.add(index, action); + + updateActionLengths(actions, version); + updateAddresses(actions, startIp); + updateJumps(actions, jumps, containerLastActions, endAddress); + updateActionStores(actions, jumps); + updateContainerSizes(actions, containerLastActions); + + return true; + } + + private static Action readActionListAtPos(List listeners, ConstantPool cpool, + SWFInputStream sis, Map actions, Map nextOffsets, + long ip, long startIp, long endIp, String path, boolean indeterminate, List visitedContainers) throws IOException { + + Action entryAction = null; + + if (visitedContainers.contains(ip)) { + return null; + } + visitedContainers.add(ip); + + Queue jumpQueue = new LinkedList<>(); + jumpQueue.add(ip); + while (!jumpQueue.isEmpty()) { + ip = jumpQueue.remove(); + if (ip < startIp) { + continue; + } + + while (endIp == -1 || endIp > ip) { + sis.seek((int) ip); + + Action a; + if ((a = sis.readAction()) == null) { + break; + } + + int actionLengthWithHeader = a.getTotalActionLength(); + + // unknown action, replace with jump + if (a instanceof ActionNop) { + ActionJump aJump = new ActionDeobfuscateJump(0); + int jumpLength = aJump.getTotalActionLength(); + aJump.setAddress(a.getAddress()); + aJump.setJumpOffset(actionLengthWithHeader - jumpLength); + a = aJump; + actionLengthWithHeader = a.getTotalActionLength(); + } + + if (entryAction == null) { + entryAction = a; + } + + Action existingAction = actions.get(ip); + if (existingAction != null) { + break; + } + + actions.put(ip, a); + nextOffsets.put(ip, ip + actionLengthWithHeader); + + long pos = sis.getPos(); + long length = pos + sis.available(); + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).progressReading(pos, length); + } + + a.setAddress(ip); + + if (a instanceof ActionPush && cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } else if (a instanceof ActionConstantPool) { + cpool = new ConstantPool(((ActionConstantPool) a).constantPool); + } else if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + long nIp = ip + actionLengthWithHeader + aIf.getJumpOffset(); + if (nIp >= 0) { + jumpQueue.add(nIp); + } + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + long nIp = ip + actionLengthWithHeader + aJump.getJumpOffset(); + if (nIp >= 0) { + jumpQueue.add(nIp); + } + break; + } else if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + String cntName = cnt.getName(); + String newPath = path + (cntName == null ? "" : "/" + cntName); + for (long size : cnt.getContainerSizes()) { + if (size != 0) { + long ip2 = ip + actionLengthWithHeader; + long endIp2 = ip + actionLengthWithHeader + size; + readActionListAtPos(listeners, cpool, + sis, actions, nextOffsets, + ip2, startIp, endIp2, newPath, indeterminate, visitedContainers); + actionLengthWithHeader += size; + } + } + } + + ip += actionLengthWithHeader; + + if (a.isExit()) { + break; + } + } + } + return entryAction; + } + + private static void deobfustaceActionListAtPosRecursive(List listeners, List output, HashMap> containers, ActionLocalData localData, TranslateStack stack, ConstantPool cpool, List actions, int ip, List ret, int startIp, int endip, String path, Map visited, boolean indeterminate, Map> decisionStates, int version, int recursionLevel, int maxRecursionLevel) throws IOException, InterruptedException { + boolean debugMode = false; + boolean decideBranch = false; + + if (recursionLevel > maxRecursionLevel + 1) { + throw new TranslateException("deobfustaceActionListAtPosRecursive max recursion level reached."); + } + + Action a; + Scanner sc = null; + loopip: + while (((endip == -1) || (endip > ip)) && (a = actions.get(ip)) != null) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + + int actionLen = a.getTotalActionLength(); + if (!visited.containsKey(ip)) { + visited.put(ip, 0); + } + int curVisited = visited.get(ip); + curVisited++; + visited.put(ip, curVisited); + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).progressDeobfuscating(ip, actions.size()); + } + int info = a.getTotalActionLength(); + + if (a instanceof ActionPush) { + if (cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } + } + + if (debugMode) { + String atos = a.getASMSource(new ActionList(), new HashSet(), ScriptExportMode.PCODE); + if (a instanceof GraphSourceItemContainer) { + atos = a.toString(); + } + System.err.println("readActionListAtPos ip: " + (ip - startIp) + " (0x" + Helper.formatAddress(ip - startIp) + ") " + " action(len " + a.actionLength + "): " + atos + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Helper.stackToString(stack, LocalData.create(cpool)) + " " + Helper.byteArrToString(a.getBytes(version))); + System.err.print("variables: "); + for (Map.Entry v : localData.variables.entrySet()) { + System.err.print("'" + v + "' = " + v.getValue().toString(LocalData.create(cpool)) + ", "); + } + System.err.println(); + String add = ""; + if (a instanceof ActionIf) { + add = " change: " + ((ActionIf) a).getJumpOffset(); + } + if (a instanceof ActionJump) { + add = " change: " + ((ActionJump) a).getJumpOffset(); + } + System.err.println(add); + } + + int newip = -1; + + if (a instanceof ActionConstantPool) { + if (cpool == null) { + cpool = new ConstantPool(); + } + cpool.setNew(((ActionConstantPool) a).constantPool); + } + ActionIf aif = null; + boolean goaif = false; + if (!a.isIgnored()) { + String varname = null; + if (a instanceof StoreTypeAction) { + StoreTypeAction sta = (StoreTypeAction) a; + varname = sta.getVariableName(stack, cpool); + } + + try { + if (a instanceof ActionIf) { + aif = (ActionIf) a; + + GraphTargetItem top = stack.pop(); + int nip = ip + actionLen + aif.getJumpOffset(); + + if (decideBranch) { + System.out.print("newip " + nip + ", "); + System.out.print("Action: jump(j),ignore(i),compute(c)?"); + if (sc == null) { + sc = new Scanner(System.in); + } + String next = sc.next(); + switch (next) { + case "j": + newip = nip; + break; + case "i": + break; + case "c": + goaif = true; + break; + } + } else if (top.isCompileTime() && (!top.hasSideEffect())) { + if (debugMode) { + System.err.print("is compiletime -> "); + } + if (EcmaScript.toBoolean(top.getResult())) { + newip = nip; + aif.jumpUsed = true; + if (debugMode) { + System.err.println("jump"); + } + } else { + aif.ignoreUsed = true; + if (debugMode) { + System.err.println("ignore"); + } + } + } else { + if (debugMode) { + System.err.println("goaif"); + } + goaif = true; + } + } else if (a instanceof ActionJump) { + newip = ip + actionLen + ((ActionJump) a).getJumpOffset(); + } else if (!(a instanceof GraphSourceItemContainer)) { + //return in for..in, TODO:Handle this better way + if (((a instanceof ActionEquals) || (a instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) { + stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); + } + if ((a instanceof ActionStoreRegister) && stack.isEmpty()) { + stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); + } + a.translate(localData, stack, output, Graph.SOP_USE_STATIC/*Graph.SOP_SKIP_STATIC*/, path); + } + } catch (RuntimeException ex) { + logger.log(Level.SEVERE, "Disassembly exception", ex); + break; + } + + HashMap vars = localData.variables; + if (varname != null) { + GraphTargetItem varval = vars.get(varname); + if (varval != null && varval.isCompileTime() && indeterminate) { + vars.put(varname, new NotCompileTimeItem(null, varval)); + } + } + } + for (int i = 0; i < actionLen; i++) { + ret.set(ip + i, a); + } + + if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + if (a instanceof Action) { + long endAddr = a.getAddress() + cnt.getHeaderSize(); + String cntName = cnt.getName(); + List> output2s = new ArrayList<>(); + for (long size : cnt.getContainerSizes()) { + if (size == 0) { + output2s.add(new ArrayList()); + continue; + } + ActionLocalData localData2; + List output2 = new ArrayList<>(); + if ((cnt instanceof ActionDefineFunction) || (cnt instanceof ActionDefineFunction2)) { + localData2 = new ActionLocalData(); + } else { + localData2 = localData; + } + deobfustaceActionListAtPosRecursive(listeners, output2, containers, localData2, new TranslateStack(path), cpool, actions, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); + output2s.add(output2); + endAddr += size; + } + cnt.translateContainer(output2s, stack, output, localData.regNames, localData.variables, localData.functions); + ip = (int) endAddr; + continue; + } + } + + if (a instanceof ActionEnd) { + break; + } + if (goaif) { + aif.ignoreUsed = true; + aif.jumpUsed = true; + indeterminate = true; + + HashMap vars = localData.variables; + boolean stateChanged = false; + if (decisionStates.containsKey(ip)) { + HashMap oldstate = decisionStates.get(ip); + if (oldstate.size() != vars.size()) { + stateChanged = true; + } else { + for (String k : vars.keySet()) { + if (!oldstate.containsKey(k)) { + stateChanged = true; + break; + } + if (!vars.get(k).isCompileTime() && oldstate.get(k).isCompileTime()) { + stateChanged = true; + break; + } + } + } + } + HashMap curstate = new HashMap<>(); + curstate.putAll(vars); + decisionStates.put(ip, curstate); + + if ((!stateChanged) && curVisited > 1) { + List branches = new ArrayList<>(); + branches.add(ip + actionLen + aif.getJumpOffset()); + branches.add(ip + actionLen); + for (int br : branches) { + int visc = 0; + if (visited.containsKey(br)) { + visc = visited.get(br); + } + if (visc == 0) {//(localData.regNames), + new HashMap<>(localData.variables), new HashMap<>(localData.functions)); + deobfustaceActionListAtPosRecursive(listeners, output, containers, subLocalData, subStack, cpool, actions, ip + actionLen + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); + } + + if (newip > -1) { + ip = newip; + } else { + ip += info; + } + + if (a.isExit()) { + break; + } + } + for (DisassemblyListener listener : listeners) { + listener.progressDeobfuscating(ip, actions.size()); + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java index 802b3342c..b51764d96 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java @@ -223,7 +223,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple { private void executeActions(ActionList actions, int idx, int endIdx, ActionConstantPool constantPool, ExecutionResult result, Map fakeFunctions) { List output = new ArrayList<>(); ActionLocalData localData = new ActionLocalData(); - FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(); + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); int instructionsProcessed = 0; ActionConstantPool lastConstantPool = null; @@ -442,7 +442,7 @@ public class ActionDeobfuscator extends ActionDeobfuscatorSimple { public Set defines = new HashSet<>(); - public TranslateStack stack = new TranslateStack(); + public TranslateStack stack = new TranslateStack("?"); public Object resultValue; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java index 2bea33d89..6b90466f7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java @@ -273,7 +273,7 @@ public class ActionDeobfuscatorSimple implements SWFDecompilerListener { private void executeActions(ActionList actions, int idx, int endIdx, ExecutionResult result) { List output = new ArrayList<>(); ActionLocalData localData = new ActionLocalData(); - FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(); + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); int instructionsProcessed = 0; try { @@ -388,7 +388,7 @@ public class ActionDeobfuscatorSimple implements SWFDecompilerListener { public int instructionsProcessed = -1; - public TranslateStack stack = new TranslateStack(); + public TranslateStack stack = new TranslateStack("?"); public Object resultValue; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java index 133476812..677710042 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.deobfuscation; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -26,6 +27,10 @@ public class FixItemCounterTranslateStack extends TranslateStack { private int fixItemCount = Integer.MAX_VALUE; + public FixItemCounterTranslateStack(String path) { + super(null); //null path => do not add PushItems + } + @Override public GraphTargetItem pop() { GraphTargetItem result = super.pop(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java index 8536e4da7..4dc97afc0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.Helper; @@ -34,7 +35,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; -public class DirectValueActionItem extends ActionItem { +public class DirectValueActionItem extends ActionItem implements SimpleValue { public Object value; @@ -91,6 +92,11 @@ public class DirectValueActionItem extends ActionItem { return value; } + @Override + public boolean isSimpleValue() { + return !(value instanceof RegisterNumber); + } + @Override public String toStringNoQuotes(LocalData localData) { if (value instanceof Double) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/EnumerateActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/EnumerateActionItem.java index 99809b9aa..e286e5053 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/EnumerateActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/EnumerateActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; @@ -41,8 +42,9 @@ public class EnumerateActionItem extends ActionItem { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("enumerate "); - return object.toString(writer, localData); + writer.append("§§enumerate("); + object.toString(writer, localData); + return writer.append(")"); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/EqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/EqActionItem.java index 1508f005f..4408950b3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/EqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/EqActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -48,7 +49,7 @@ public class EqActionItem extends BinaryOpItem implements LogicalOpItem { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new NeqActionItem(src, leftSide, rightSide, version2); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GeActionItem.java index 30bb365a3..c33f6375f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GeActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -58,7 +59,7 @@ public class GeActionItem extends BinaryOpItem implements LogicalOpItem, Inverte } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new LtActionItem(src, leftSide, rightSide, version2); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GtActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GtActionItem.java index 7cb210db6..29b3a6528 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GtActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/GtActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -42,7 +43,7 @@ public class GtActionItem extends BinaryOpItem implements LogicalOpItem { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new LeActionItem(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/Inverted.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/Inverted.java index 834c918ec..df7e5ac6e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/Inverted.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/Inverted.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; +import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; /** @@ -23,5 +25,5 @@ import com.jpexs.decompiler.graph.GraphTargetItem; */ public interface Inverted { - public GraphTargetItem invert(); + public GraphTargetItem invert(GraphSourceItem src); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LeActionItem.java index 9cbeb028a..76ef25950 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LeActionItem.java @@ -50,7 +50,7 @@ public class LeActionItem extends BinaryOpItem implements LogicalOpItem, Inverte } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new GtActionItem(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LtActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LtActionItem.java index 87f51504d..9d4b8c702 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LtActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/LtActionItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.model.operations; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -50,7 +51,7 @@ public class LtActionItem extends BinaryOpItem implements LogicalOpItem { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem neqSrc) { return new GeActionItem(src, leftSide, rightSide, version2); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/NeqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/NeqActionItem.java index 463efa58a..2b2a31bfd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/NeqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/NeqActionItem.java @@ -49,7 +49,7 @@ public class NeqActionItem extends BinaryOpItem implements LogicalOpItem, Invert } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new EqActionItem(src, leftSide, rightSide, version2); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictEqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictEqActionItem.java index 91ab8b2cc..c25133620 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictEqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictEqActionItem.java @@ -42,7 +42,7 @@ public class StrictEqActionItem extends BinaryOpItem implements LogicalOpItem, I } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StrictNeqActionItem(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictNeqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictNeqActionItem.java index f7331a689..47f6986da 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictNeqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StrictNeqActionItem.java @@ -43,7 +43,7 @@ public class StrictNeqActionItem extends BinaryOpItem implements LogicalOpItem, } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StrictEqActionItem(src, leftSide, rightSide); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringEqActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringEqActionItem.java index 0b0d9a432..f122b47de 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringEqActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringEqActionItem.java @@ -48,7 +48,7 @@ public class StringEqActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringNeActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGeActionItem.java index 84c262ffd..dabc07d66 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGeActionItem.java @@ -49,7 +49,7 @@ public class StringGeActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringLtActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGtActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGtActionItem.java index 941d8d00e..1df7f826a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGtActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringGtActionItem.java @@ -54,7 +54,7 @@ public class StringGtActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringLeActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLeActionItem.java index 4815f27cd..4f42a55b2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLeActionItem.java @@ -57,7 +57,7 @@ public class StringLeActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringGtActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLtActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLtActionItem.java index f90ac8046..c85bfa334 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLtActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringLtActionItem.java @@ -48,7 +48,7 @@ public class StringLtActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringGeActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringNeActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringNeActionItem.java index f24f2d5da..9027886d3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringNeActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/StringNeActionItem.java @@ -49,7 +49,7 @@ public class StringNeActionItem extends BinaryOpItem implements Inverted { } @Override - public GraphTargetItem invert() { + public GraphTargetItem invert(GraphSourceItem negSrc) { return new StringEqActionItem(src, leftSide, rightSide); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java index 04477c044..12a1d8506 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java @@ -17,1253 +17,1207 @@ * License along with this library. */ package com.jpexs.decompiler.flash.action.parser.script; - import com.jpexs.decompiler.flash.action.parser.ActionParseException; import java.util.ArrayList; import java.util.List; import java.util.Stack; + /** - * This class is a scanner generated by - * JFlex 1.6.0 from the specification file - * D:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript_script.flex + * This class is a scanner generated by + * JFlex 1.6.0 + * from the specification file C:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript_script.flex */ public final class ActionScriptLexer { - /** - * This character denotes the end of file - */ - public static final int YYEOF = -1; + /** This character denotes the end of file */ + public static final int YYEOF = -1; - /** - * initial size of the lookahead buffer - */ - private static final int ZZ_BUFFERSIZE = 16384; + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; - /** - * lexical states - */ - public static final int YYINITIAL = 0; + /** lexical states */ + public static final int YYINITIAL = 0; + public static final int STRING = 2; + public static final int CHARLITERAL = 4; + public static final int XMLSTARTTAG = 6; + public static final int XML = 8; + public static final int OIDENTIFIER = 10; - public static final int STRING = 2; + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 + }; - public static final int CHARLITERAL = 4; + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\7\1\3\1\2\1\121\1\122\1\1\16\7\4\0\1\14\1\110"+ + "\1\16\1\0\1\6\1\117\1\113\1\30\1\100\1\101\1\5\1\115"+ + "\1\107\1\26\1\11\1\4\1\17\3\23\4\24\2\20\1\10\1\106"+ + "\1\12\1\15\1\13\1\112\1\120\1\62\1\22\1\72\1\73\1\25"+ + "\1\64\1\6\1\66\1\77\2\6\1\70\1\71\1\76\1\6\1\75"+ + "\1\67\1\6\1\63\1\65\1\61\1\74\1\6\1\21\2\6\1\104"+ + "\1\27\1\105\1\116\1\6\1\0\1\35\1\32\1\37\1\46\1\34"+ + "\1\47\1\60\1\52\1\44\1\6\1\36\1\50\1\55\1\42\1\41"+ + "\1\53\1\6\1\33\1\40\1\43\1\45\1\56\1\51\1\57\1\54"+ + "\1\6\1\102\1\114\1\103\1\111\6\7\1\123\32\7\2\0\4\6"+ + "\1\0\1\31\2\0\1\6\2\0\1\7\7\0\1\6\4\0\1\6"+ + "\5\0\27\6\1\0\37\6\1\0\u01ca\6\4\0\14\6\16\0\5\6"+ + "\7\0\1\6\1\0\1\6\21\0\160\7\5\6\1\0\2\6\2\0"+ + "\4\6\10\0\1\6\1\0\3\6\1\0\1\6\1\0\24\6\1\0"+ + "\123\6\1\0\213\6\1\0\5\7\2\0\236\6\11\0\46\6\2\0"+ + "\1\6\7\0\47\6\7\0\1\6\1\0\55\7\1\0\1\7\1\0"+ + "\2\7\1\0\2\7\1\0\1\7\10\0\33\6\5\0\3\6\15\0"+ + "\5\7\6\0\1\6\4\0\13\7\5\0\53\6\37\7\4\0\2\6"+ + "\1\7\143\6\1\0\1\6\10\7\1\0\6\7\2\6\2\7\1\0"+ + "\4\7\2\6\12\7\3\6\2\0\1\6\17\0\1\7\1\6\1\7"+ + "\36\6\33\7\2\0\131\6\13\7\1\6\16\0\12\7\41\6\11\7"+ + "\2\6\4\0\1\6\5\0\26\6\4\7\1\6\11\7\1\6\3\7"+ + "\1\6\5\7\22\0\31\6\3\7\104\0\1\6\1\0\13\6\67\0"+ + "\33\7\1\0\4\7\66\6\3\7\1\6\22\7\1\6\7\7\12\6"+ + "\2\7\2\0\12\7\1\0\7\6\1\0\7\6\1\0\3\7\1\0"+ + "\10\6\2\0\2\6\2\0\26\6\1\0\7\6\1\0\1\6\3\0"+ + "\4\6\2\0\1\7\1\6\7\7\2\0\2\7\2\0\3\7\1\6"+ + "\10\0\1\7\4\0\2\6\1\0\3\6\2\7\2\0\12\7\4\6"+ + "\7\0\1\6\5\0\3\7\1\0\6\6\4\0\2\6\2\0\26\6"+ + "\1\0\7\6\1\0\2\6\1\0\2\6\1\0\2\6\2\0\1\7"+ + "\1\0\5\7\4\0\2\7\2\0\3\7\3\0\1\7\7\0\4\6"+ + "\1\0\1\6\7\0\14\7\3\6\1\7\13\0\3\7\1\0\11\6"+ + "\1\0\3\6\1\0\26\6\1\0\7\6\1\0\2\6\1\0\5\6"+ + "\2\0\1\7\1\6\10\7\1\0\3\7\1\0\3\7\2\0\1\6"+ + "\17\0\2\6\2\7\2\0\12\7\1\0\1\6\17\0\3\7\1\0"+ + "\10\6\2\0\2\6\2\0\26\6\1\0\7\6\1\0\2\6\1\0"+ + "\5\6\2\0\1\7\1\6\7\7\2\0\2\7\2\0\3\7\10\0"+ + "\2\7\4\0\2\6\1\0\3\6\2\7\2\0\12\7\1\0\1\6"+ + "\20\0\1\7\1\6\1\0\6\6\3\0\3\6\1\0\4\6\3\0"+ + "\2\6\1\0\1\6\1\0\2\6\3\0\2\6\3\0\3\6\3\0"+ + "\14\6\4\0\5\7\3\0\3\7\1\0\4\7\2\0\1\6\6\0"+ + "\1\7\16\0\12\7\11\0\1\6\7\0\3\7\1\0\10\6\1\0"+ + "\3\6\1\0\27\6\1\0\12\6\1\0\5\6\3\0\1\6\7\7"+ + "\1\0\3\7\1\0\4\7\7\0\2\7\1\0\2\6\6\0\2\6"+ + "\2\7\2\0\12\7\22\0\2\7\1\0\10\6\1\0\3\6\1\0"+ + "\27\6\1\0\12\6\1\0\5\6\2\0\1\7\1\6\7\7\1\0"+ + "\3\7\1\0\4\7\7\0\2\7\7\0\1\6\1\0\2\6\2\7"+ + "\2\0\12\7\1\0\2\6\17\0\2\7\1\0\10\6\1\0\3\6"+ + "\1\0\51\6\2\0\1\6\7\7\1\0\3\7\1\0\4\7\1\6"+ + "\10\0\1\7\10\0\2\6\2\7\2\0\12\7\12\0\6\6\2\0"+ + "\2\7\1\0\22\6\3\0\30\6\1\0\11\6\1\0\1\6\2\0"+ + "\7\6\3\0\1\7\4\0\6\7\1\0\1\7\1\0\10\7\22\0"+ + "\2\7\15\0\60\6\1\7\2\6\7\7\4\0\10\6\10\7\1\0"+ + "\12\7\47\0\2\6\1\0\1\6\2\0\2\6\1\0\1\6\2\0"+ + "\1\6\6\0\4\6\1\0\7\6\1\0\3\6\1\0\1\6\1\0"+ + "\1\6\2\0\2\6\1\0\4\6\1\7\2\6\6\7\1\0\2\7"+ + "\1\6\2\0\5\6\1\0\1\6\1\0\6\7\2\0\12\7\2\0"+ + "\4\6\40\0\1\6\27\0\2\7\6\0\12\7\13\0\1\7\1\0"+ + "\1\7\1\0\1\7\4\0\2\7\10\6\1\0\44\6\4\0\24\7"+ + "\1\0\2\7\5\6\13\7\1\0\44\7\11\0\1\7\71\0\53\6"+ + "\24\7\1\6\12\7\6\0\6\6\4\7\4\6\3\7\1\6\3\7"+ + "\2\6\7\7\3\6\4\7\15\6\14\7\1\6\17\7\2\0\46\6"+ + "\1\0\1\6\5\0\1\6\2\0\53\6\1\0\u014d\6\1\0\4\6"+ + "\2\0\7\6\1\0\1\6\1\0\4\6\2\0\51\6\1\0\4\6"+ + "\2\0\41\6\1\0\4\6\2\0\7\6\1\0\1\6\1\0\4\6"+ + "\2\0\17\6\1\0\71\6\1\0\4\6\2\0\103\6\2\0\3\7"+ + "\40\0\20\6\20\0\125\6\14\0\u026c\6\2\0\21\6\1\0\32\6"+ + "\5\0\113\6\3\0\3\6\17\0\15\6\1\0\4\6\3\7\13\0"+ + "\22\6\3\7\13\0\22\6\2\7\14\0\15\6\1\0\3\6\1\0"+ + "\2\7\14\0\64\6\40\7\3\0\1\6\3\0\2\6\1\7\2\0"+ + "\12\7\41\0\3\7\2\0\12\7\6\0\130\6\10\0\51\6\1\7"+ + "\1\6\5\0\106\6\12\0\35\6\3\0\14\7\4\0\14\7\12\0"+ + "\12\7\36\6\2\0\5\6\13\0\54\6\4\0\21\7\7\6\2\7"+ + "\6\0\12\7\46\0\27\6\5\7\4\0\65\6\12\7\1\0\35\7"+ + "\2\0\13\7\6\0\12\7\15\0\1\6\130\0\5\7\57\6\21\7"+ + "\7\6\4\0\12\7\21\0\11\7\14\0\3\7\36\6\15\7\2\6"+ + "\12\7\54\6\16\7\14\0\44\6\24\7\10\0\12\7\3\0\3\6"+ + "\12\7\44\6\122\0\3\7\1\0\25\7\4\6\1\7\4\6\3\7"+ + "\2\6\11\0\300\6\47\7\25\0\4\7\u0116\6\2\0\6\6\2\0"+ + "\46\6\2\0\6\6\2\0\10\6\1\0\1\6\1\0\1\6\1\0"+ + "\1\6\1\0\37\6\2\0\65\6\1\0\7\6\1\0\1\6\3\0"+ + "\3\6\1\0\7\6\3\0\4\6\2\0\6\6\4\0\15\6\5\0"+ + "\3\6\1\0\7\6\16\0\5\7\30\0\1\121\1\121\5\7\20\0"+ + "\2\6\23\0\1\6\13\0\5\7\5\0\6\7\1\0\1\6\15\0"+ + "\1\6\20\0\15\6\3\0\33\6\25\0\15\7\4\0\1\7\3\0"+ + "\14\7\21\0\1\6\4\0\1\6\2\0\12\6\1\0\1\6\3\0"+ + "\5\6\6\0\1\6\1\0\1\6\1\0\1\6\1\0\4\6\1\0"+ + "\13\6\2\0\4\6\5\0\5\6\4\0\1\6\21\0\51\6\u0a77\0"+ + "\57\6\1\0\57\6\1\0\205\6\6\0\4\6\3\7\2\6\14\0"+ + "\46\6\1\0\1\6\5\0\1\6\2\0\70\6\7\0\1\6\17\0"+ + "\1\7\27\6\11\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6"+ + "\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6\1\0\40\7"+ + "\57\0\1\6\u01d5\0\3\6\31\0\11\6\6\7\1\0\5\6\2\0"+ + "\5\6\4\0\126\6\2\0\2\7\2\0\3\6\1\0\132\6\1\0"+ + "\4\6\5\0\51\6\3\0\136\6\21\0\33\6\65\0\20\6\u0200\0"+ + "\u19b6\6\112\0\u51cd\6\63\0\u048d\6\103\0\56\6\2\0\u010d\6\3\0"+ + "\20\6\12\7\2\6\24\0\57\6\1\7\4\0\12\7\1\0\31\6"+ + "\7\0\1\7\120\6\2\7\45\0\11\6\2\0\147\6\2\0\4\6"+ + "\1\0\4\6\14\0\13\6\115\0\12\6\1\7\3\6\1\7\4\6"+ + "\1\7\27\6\5\7\20\0\1\6\7\0\64\6\14\0\2\7\62\6"+ + "\21\7\13\0\12\7\6\0\22\7\6\6\3\0\1\6\4\0\12\7"+ + "\34\6\10\7\2\0\27\6\15\7\14\0\35\6\3\0\4\7\57\6"+ + "\16\7\16\0\1\6\12\7\46\0\51\6\16\7\11\0\3\6\1\7"+ + "\10\6\2\7\2\0\12\7\6\0\27\6\3\0\1\6\1\7\4\0"+ + "\60\6\1\7\1\6\3\7\2\6\2\7\5\6\2\7\1\6\1\7"+ + "\1\6\30\0\3\6\2\0\13\6\5\7\2\0\3\6\2\7\12\0"+ + "\6\6\2\0\6\6\2\0\6\6\11\0\7\6\1\0\7\6\221\0"+ + "\43\6\10\7\1\0\2\7\2\0\12\7\6\0\u2ba4\6\14\0\27\6"+ + "\4\0\61\6\u2104\0\u016e\6\2\0\152\6\46\0\7\6\14\0\5\6"+ + "\5\0\1\6\1\7\12\6\1\0\15\6\1\0\5\6\1\0\1\6"+ + "\1\0\2\6\1\0\2\6\1\0\154\6\41\0\u016b\6\22\0\100\6"+ + "\2\0\66\6\50\0\15\6\3\0\20\7\20\0\7\7\14\0\2\6"+ + "\30\0\3\6\31\0\1\6\6\0\5\6\1\0\207\6\2\0\1\7"+ + "\4\0\1\6\13\0\12\7\7\0\32\6\4\0\1\6\1\0\32\6"+ + "\13\0\131\6\3\0\6\6\2\0\6\6\2\0\6\6\2\0\3\6"+ + "\3\0\2\6\3\0\2\6\22\0\3\7\4\0\14\6\1\0\32\6"+ + "\1\0\23\6\1\0\2\6\1\0\17\6\2\0\16\6\42\0\173\6"+ + "\105\0\65\6\210\0\1\7\202\0\35\6\3\0\61\6\57\0\37\6"+ + "\21\0\33\6\65\0\36\6\2\0\44\6\4\0\10\6\1\0\5\6"+ + "\52\0\236\6\2\0\12\7\u0356\0\6\6\2\0\1\6\1\0\54\6"+ + "\1\0\2\6\3\0\1\6\2\0\27\6\252\0\26\6\12\0\32\6"+ + "\106\0\70\6\6\0\2\6\100\0\1\6\3\7\1\0\2\7\5\0"+ + "\4\7\4\6\1\0\3\6\1\0\33\6\4\0\3\7\4\0\1\7"+ + "\40\0\35\6\203\0\66\6\12\0\26\6\12\0\23\6\215\0\111\6"+ + "\u03b7\0\3\7\65\6\17\7\37\0\12\7\20\0\3\7\55\6\13\7"+ + "\2\0\1\7\22\0\31\6\7\0\12\7\6\0\3\7\44\6\16\7"+ + "\1\0\12\7\100\0\3\7\60\6\16\7\4\6\13\0\12\7\u04a6\0"+ + "\53\6\15\7\10\0\12\7\u0936\0\u036f\6\221\0\143\6\u0b9d\0\u042f\6"+ + "\u33d1\0\u0239\6\u04c7\0\105\6\13\0\1\6\56\7\20\0\4\7\15\6"+ + "\u4060\0\2\6\u2163\0\5\7\3\0\26\7\2\0\7\7\36\0\4\7"+ + "\224\0\3\7\u01bb\0\125\6\1\0\107\6\1\0\2\6\2\0\1\6"+ + "\2\0\2\6\2\0\4\6\1\0\14\6\1\0\1\6\1\0\7\6"+ + "\1\0\101\6\1\0\4\6\2\0\10\6\1\0\7\6\1\0\34\6"+ + "\1\0\4\6\1\0\5\6\1\0\1\6\3\0\7\6\1\0\u0154\6"+ + "\2\0\31\6\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6"+ + "\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6\1\0\31\6"+ + "\1\0\10\6\2\0\62\7\u1600\0\4\6\1\0\33\6\1\0\2\6"+ + "\1\0\1\6\2\0\1\6\1\0\12\6\1\0\4\6\1\0\1\6"+ + "\1\0\1\6\6\0\1\6\4\0\1\6\1\0\1\6\1\0\1\6"+ + "\1\0\3\6\1\0\2\6\1\0\1\6\2\0\1\6\1\0\1\6"+ + "\1\0\1\6\1\0\1\6\1\0\1\6\1\0\2\6\1\0\1\6"+ + "\2\0\4\6\1\0\7\6\1\0\4\6\1\0\4\6\1\0\1\6"+ + "\1\0\12\6\1\0\21\6\5\0\3\6\1\0\5\6\1\0\21\6"+ + "\u1144\0\ua6d7\6\51\0\u1035\6\13\0\336\6\u3fe2\0\u021e\6\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\u05ee\0"+ + "\1\7\36\0\140\7\200\0\360\7\uffff\0\uffff\0\ufe12\0"; - public static final int XMLSTARTTAG = 6; + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - public static final int XML = 8; + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); - public static final int OIDENTIFIER = 10; + private static final String ZZ_ACTION_PACKED_0 = + "\6\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7"+ + "\1\10\1\11\1\12\1\13\1\14\2\15\1\16\1\17"+ + "\1\20\26\6\1\21\1\22\1\23\1\24\1\25\1\26"+ + "\1\27\1\30\1\31\1\32\1\33\1\34\1\35\1\36"+ + "\1\37\1\40\1\41\1\42\2\43\1\44\1\1\1\42"+ + "\1\1\2\45\1\42\1\1\1\46\2\42\2\47\2\42"+ + "\1\1\1\50\1\3\1\0\1\51\1\52\1\53\2\0"+ + "\1\54\1\0\1\55\1\56\1\57\1\60\1\61\1\62"+ + "\1\63\1\54\1\0\2\63\1\0\1\64\1\65\1\0"+ + "\7\6\1\66\11\6\1\67\12\6\1\70\1\71\1\72"+ + "\4\6\1\73\30\6\1\56\1\74\1\75\1\76\1\77"+ + "\1\100\1\101\1\102\1\103\1\104\1\105\1\104\1\106"+ + "\1\107\1\110\1\111\1\112\1\113\1\104\1\114\1\104"+ + "\6\0\1\115\1\116\2\115\2\3\2\0\1\117\3\0"+ + "\1\120\1\0\1\121\1\122\1\123\1\124\2\125\1\63"+ + "\1\54\1\0\1\126\10\6\1\127\5\6\1\130\1\131"+ + "\5\6\1\132\1\6\1\133\5\6\1\134\7\6\1\135"+ + "\2\6\1\136\10\6\1\137\20\6\1\140\1\6\1\141"+ + "\2\6\1\142\2\6\1\143\12\0\1\144\5\0\1\145"+ + "\1\125\1\63\4\6\1\146\1\147\1\150\1\6\1\151"+ + "\1\6\1\152\5\6\1\153\7\6\1\154\1\6\1\155"+ + "\4\6\1\156\22\6\1\157\7\6\1\160\4\6\1\161"+ + "\7\6\1\162\1\0\1\163\1\42\1\0\1\164\12\0"+ + "\1\125\1\63\1\165\4\6\1\166\1\167\1\6\1\170"+ + "\5\6\1\171\5\6\1\172\3\6\1\173\14\6\1\174"+ + "\6\6\1\175\2\6\1\176\3\6\1\177\1\6\1\200"+ + "\10\6\10\0\1\125\1\63\1\201\1\6\1\202\3\6"+ + "\1\203\2\6\1\204\1\205\7\6\1\206\4\6\1\207"+ + "\4\6\1\210\5\6\1\211\10\6\1\212\2\6\1\213"+ + "\3\6\1\214\1\215\1\6\2\0\1\120\1\125\1\63"+ + "\1\6\1\216\5\6\1\217\14\6\1\220\1\6\1\221"+ + "\1\6\1\222\7\6\1\223\1\224\6\6\1\42\1\125"+ + "\1\63\1\6\1\225\2\6\1\226\1\227\6\6\1\230"+ + "\7\6\1\231\5\6\1\232\1\6\1\233\1\234\3\6"+ + "\1\235\1\125\1\63\1\6\1\236\1\6\1\237\1\240"+ + "\4\6\1\241\2\6\1\242\2\6\1\243\1\244\1\6"+ + "\1\245\1\246\5\6\1\125\1\63\2\6\1\247\1\250"+ + "\1\6\1\251\1\6\1\252\6\6\1\253\2\6\1\63"+ + "\4\6\1\254\4\6\1\255\1\256\1\257\1\63\6\6"+ + "\1\260\2\6\1\63\1\6\1\261\1\6\1\262\2\6"+ + "\1\263\1\264\1\63\2\6\1\265\3\6\1\63\1\266"+ + "\4\6\1\63\2\6\1\267\1\270\1\271\1\6\1\272"; - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the - * beginning of a line l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 - }; + private static int [] zzUnpackAction() { + int [] result = new int[707]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED - = "\11\7\1\3\1\2\1\121\1\122\1\1\16\7\4\0\1\14\1\110" - + "\1\16\1\0\1\6\1\117\1\113\1\30\1\100\1\101\1\5\1\115" - + "\1\107\1\26\1\11\1\4\1\17\3\23\4\24\2\20\1\10\1\106" - + "\1\12\1\15\1\13\1\112\1\120\1\62\1\22\1\72\1\73\1\25" - + "\1\64\1\6\1\66\1\77\2\6\1\70\1\71\1\76\1\6\1\75" - + "\1\67\1\6\1\63\1\65\1\61\1\74\1\6\1\21\2\6\1\104" - + "\1\27\1\105\1\116\1\6\1\0\1\35\1\32\1\37\1\46\1\34" - + "\1\47\1\60\1\52\1\44\1\6\1\36\1\50\1\55\1\42\1\41" - + "\1\53\1\6\1\33\1\40\1\43\1\45\1\56\1\51\1\57\1\54" - + "\1\6\1\102\1\114\1\103\1\111\6\7\1\123\32\7\2\0\4\6" - + "\1\0\1\31\2\0\1\6\2\0\1\7\7\0\1\6\4\0\1\6" - + "\5\0\27\6\1\0\37\6\1\0\u01ca\6\4\0\14\6\16\0\5\6" - + "\7\0\1\6\1\0\1\6\21\0\160\7\5\6\1\0\2\6\2\0" - + "\4\6\10\0\1\6\1\0\3\6\1\0\1\6\1\0\24\6\1\0" - + "\123\6\1\0\213\6\1\0\5\7\2\0\236\6\11\0\46\6\2\0" - + "\1\6\7\0\47\6\7\0\1\6\1\0\55\7\1\0\1\7\1\0" - + "\2\7\1\0\2\7\1\0\1\7\10\0\33\6\5\0\3\6\15\0" - + "\5\7\6\0\1\6\4\0\13\7\5\0\53\6\37\7\4\0\2\6" - + "\1\7\143\6\1\0\1\6\10\7\1\0\6\7\2\6\2\7\1\0" - + "\4\7\2\6\12\7\3\6\2\0\1\6\17\0\1\7\1\6\1\7" - + "\36\6\33\7\2\0\131\6\13\7\1\6\16\0\12\7\41\6\11\7" - + "\2\6\4\0\1\6\5\0\26\6\4\7\1\6\11\7\1\6\3\7" - + "\1\6\5\7\22\0\31\6\3\7\104\0\1\6\1\0\13\6\67\0" - + "\33\7\1\0\4\7\66\6\3\7\1\6\22\7\1\6\7\7\12\6" - + "\2\7\2\0\12\7\1\0\7\6\1\0\7\6\1\0\3\7\1\0" - + "\10\6\2\0\2\6\2\0\26\6\1\0\7\6\1\0\1\6\3\0" - + "\4\6\2\0\1\7\1\6\7\7\2\0\2\7\2\0\3\7\1\6" - + "\10\0\1\7\4\0\2\6\1\0\3\6\2\7\2\0\12\7\4\6" - + "\7\0\1\6\5\0\3\7\1\0\6\6\4\0\2\6\2\0\26\6" - + "\1\0\7\6\1\0\2\6\1\0\2\6\1\0\2\6\2\0\1\7" - + "\1\0\5\7\4\0\2\7\2\0\3\7\3\0\1\7\7\0\4\6" - + "\1\0\1\6\7\0\14\7\3\6\1\7\13\0\3\7\1\0\11\6" - + "\1\0\3\6\1\0\26\6\1\0\7\6\1\0\2\6\1\0\5\6" - + "\2\0\1\7\1\6\10\7\1\0\3\7\1\0\3\7\2\0\1\6" - + "\17\0\2\6\2\7\2\0\12\7\1\0\1\6\17\0\3\7\1\0" - + "\10\6\2\0\2\6\2\0\26\6\1\0\7\6\1\0\2\6\1\0" - + "\5\6\2\0\1\7\1\6\7\7\2\0\2\7\2\0\3\7\10\0" - + "\2\7\4\0\2\6\1\0\3\6\2\7\2\0\12\7\1\0\1\6" - + "\20\0\1\7\1\6\1\0\6\6\3\0\3\6\1\0\4\6\3\0" - + "\2\6\1\0\1\6\1\0\2\6\3\0\2\6\3\0\3\6\3\0" - + "\14\6\4\0\5\7\3\0\3\7\1\0\4\7\2\0\1\6\6\0" - + "\1\7\16\0\12\7\11\0\1\6\7\0\3\7\1\0\10\6\1\0" - + "\3\6\1\0\27\6\1\0\12\6\1\0\5\6\3\0\1\6\7\7" - + "\1\0\3\7\1\0\4\7\7\0\2\7\1\0\2\6\6\0\2\6" - + "\2\7\2\0\12\7\22\0\2\7\1\0\10\6\1\0\3\6\1\0" - + "\27\6\1\0\12\6\1\0\5\6\2\0\1\7\1\6\7\7\1\0" - + "\3\7\1\0\4\7\7\0\2\7\7\0\1\6\1\0\2\6\2\7" - + "\2\0\12\7\1\0\2\6\17\0\2\7\1\0\10\6\1\0\3\6" - + "\1\0\51\6\2\0\1\6\7\7\1\0\3\7\1\0\4\7\1\6" - + "\10\0\1\7\10\0\2\6\2\7\2\0\12\7\12\0\6\6\2\0" - + "\2\7\1\0\22\6\3\0\30\6\1\0\11\6\1\0\1\6\2\0" - + "\7\6\3\0\1\7\4\0\6\7\1\0\1\7\1\0\10\7\22\0" - + "\2\7\15\0\60\6\1\7\2\6\7\7\4\0\10\6\10\7\1\0" - + "\12\7\47\0\2\6\1\0\1\6\2\0\2\6\1\0\1\6\2\0" - + "\1\6\6\0\4\6\1\0\7\6\1\0\3\6\1\0\1\6\1\0" - + "\1\6\2\0\2\6\1\0\4\6\1\7\2\6\6\7\1\0\2\7" - + "\1\6\2\0\5\6\1\0\1\6\1\0\6\7\2\0\12\7\2\0" - + "\4\6\40\0\1\6\27\0\2\7\6\0\12\7\13\0\1\7\1\0" - + "\1\7\1\0\1\7\4\0\2\7\10\6\1\0\44\6\4\0\24\7" - + "\1\0\2\7\5\6\13\7\1\0\44\7\11\0\1\7\71\0\53\6" - + "\24\7\1\6\12\7\6\0\6\6\4\7\4\6\3\7\1\6\3\7" - + "\2\6\7\7\3\6\4\7\15\6\14\7\1\6\17\7\2\0\46\6" - + "\1\0\1\6\5\0\1\6\2\0\53\6\1\0\u014d\6\1\0\4\6" - + "\2\0\7\6\1\0\1\6\1\0\4\6\2\0\51\6\1\0\4\6" - + "\2\0\41\6\1\0\4\6\2\0\7\6\1\0\1\6\1\0\4\6" - + "\2\0\17\6\1\0\71\6\1\0\4\6\2\0\103\6\2\0\3\7" - + "\40\0\20\6\20\0\125\6\14\0\u026c\6\2\0\21\6\1\0\32\6" - + "\5\0\113\6\3\0\3\6\17\0\15\6\1\0\4\6\3\7\13\0" - + "\22\6\3\7\13\0\22\6\2\7\14\0\15\6\1\0\3\6\1\0" - + "\2\7\14\0\64\6\40\7\3\0\1\6\3\0\2\6\1\7\2\0" - + "\12\7\41\0\3\7\2\0\12\7\6\0\130\6\10\0\51\6\1\7" - + "\1\6\5\0\106\6\12\0\35\6\3\0\14\7\4\0\14\7\12\0" - + "\12\7\36\6\2\0\5\6\13\0\54\6\4\0\21\7\7\6\2\7" - + "\6\0\12\7\46\0\27\6\5\7\4\0\65\6\12\7\1\0\35\7" - + "\2\0\13\7\6\0\12\7\15\0\1\6\130\0\5\7\57\6\21\7" - + "\7\6\4\0\12\7\21\0\11\7\14\0\3\7\36\6\15\7\2\6" - + "\12\7\54\6\16\7\14\0\44\6\24\7\10\0\12\7\3\0\3\6" - + "\12\7\44\6\122\0\3\7\1\0\25\7\4\6\1\7\4\6\3\7" - + "\2\6\11\0\300\6\47\7\25\0\4\7\u0116\6\2\0\6\6\2\0" - + "\46\6\2\0\6\6\2\0\10\6\1\0\1\6\1\0\1\6\1\0" - + "\1\6\1\0\37\6\2\0\65\6\1\0\7\6\1\0\1\6\3\0" - + "\3\6\1\0\7\6\3\0\4\6\2\0\6\6\4\0\15\6\5\0" - + "\3\6\1\0\7\6\16\0\5\7\30\0\1\121\1\121\5\7\20\0" - + "\2\6\23\0\1\6\13\0\5\7\5\0\6\7\1\0\1\6\15\0" - + "\1\6\20\0\15\6\3\0\33\6\25\0\15\7\4\0\1\7\3\0" - + "\14\7\21\0\1\6\4\0\1\6\2\0\12\6\1\0\1\6\3\0" - + "\5\6\6\0\1\6\1\0\1\6\1\0\1\6\1\0\4\6\1\0" - + "\13\6\2\0\4\6\5\0\5\6\4\0\1\6\21\0\51\6\u0a77\0" - + "\57\6\1\0\57\6\1\0\205\6\6\0\4\6\3\7\2\6\14\0" - + "\46\6\1\0\1\6\5\0\1\6\2\0\70\6\7\0\1\6\17\0" - + "\1\7\27\6\11\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6" - + "\1\0\7\6\1\0\7\6\1\0\7\6\1\0\7\6\1\0\40\7" - + "\57\0\1\6\u01d5\0\3\6\31\0\11\6\6\7\1\0\5\6\2\0" - + "\5\6\4\0\126\6\2\0\2\7\2\0\3\6\1\0\132\6\1\0" - + "\4\6\5\0\51\6\3\0\136\6\21\0\33\6\65\0\20\6\u0200\0" - + "\u19b6\6\112\0\u51cd\6\63\0\u048d\6\103\0\56\6\2\0\u010d\6\3\0" - + "\20\6\12\7\2\6\24\0\57\6\1\7\4\0\12\7\1\0\31\6" - + "\7\0\1\7\120\6\2\7\45\0\11\6\2\0\147\6\2\0\4\6" - + "\1\0\4\6\14\0\13\6\115\0\12\6\1\7\3\6\1\7\4\6" - + "\1\7\27\6\5\7\20\0\1\6\7\0\64\6\14\0\2\7\62\6" - + "\21\7\13\0\12\7\6\0\22\7\6\6\3\0\1\6\4\0\12\7" - + "\34\6\10\7\2\0\27\6\15\7\14\0\35\6\3\0\4\7\57\6" - + "\16\7\16\0\1\6\12\7\46\0\51\6\16\7\11\0\3\6\1\7" - + "\10\6\2\7\2\0\12\7\6\0\27\6\3\0\1\6\1\7\4\0" - + "\60\6\1\7\1\6\3\7\2\6\2\7\5\6\2\7\1\6\1\7" - + "\1\6\30\0\3\6\2\0\13\6\5\7\2\0\3\6\2\7\12\0" - + "\6\6\2\0\6\6\2\0\6\6\11\0\7\6\1\0\7\6\221\0" - + "\43\6\10\7\1\0\2\7\2\0\12\7\6\0\u2ba4\6\14\0\27\6" - + "\4\0\61\6\u2104\0\u016e\6\2\0\152\6\46\0\7\6\14\0\5\6" - + "\5\0\1\6\1\7\12\6\1\0\15\6\1\0\5\6\1\0\1\6" - + "\1\0\2\6\1\0\2\6\1\0\154\6\41\0\u016b\6\22\0\100\6" - + "\2\0\66\6\50\0\15\6\3\0\20\7\20\0\7\7\14\0\2\6" - + "\30\0\3\6\31\0\1\6\6\0\5\6\1\0\207\6\2\0\1\7" - + "\4\0\1\6\13\0\12\7\7\0\32\6\4\0\1\6\1\0\32\6" - + "\13\0\131\6\3\0\6\6\2\0\6\6\2\0\6\6\2\0\3\6" - + "\3\0\2\6\3\0\2\6\22\0\3\7\4\0\14\6\1\0\32\6" - + "\1\0\23\6\1\0\2\6\1\0\17\6\2\0\16\6\42\0\173\6" - + "\105\0\65\6\210\0\1\7\202\0\35\6\3\0\61\6\57\0\37\6" - + "\21\0\33\6\65\0\36\6\2\0\44\6\4\0\10\6\1\0\5\6" - + "\52\0\236\6\2\0\12\7\u0356\0\6\6\2\0\1\6\1\0\54\6" - + "\1\0\2\6\3\0\1\6\2\0\27\6\252\0\26\6\12\0\32\6" - + "\106\0\70\6\6\0\2\6\100\0\1\6\3\7\1\0\2\7\5\0" - + "\4\7\4\6\1\0\3\6\1\0\33\6\4\0\3\7\4\0\1\7" - + "\40\0\35\6\203\0\66\6\12\0\26\6\12\0\23\6\215\0\111\6" - + "\u03b7\0\3\7\65\6\17\7\37\0\12\7\20\0\3\7\55\6\13\7" - + "\2\0\1\7\22\0\31\6\7\0\12\7\6\0\3\7\44\6\16\7" - + "\1\0\12\7\100\0\3\7\60\6\16\7\4\6\13\0\12\7\u04a6\0" - + "\53\6\15\7\10\0\12\7\u0936\0\u036f\6\221\0\143\6\u0b9d\0\u042f\6" - + "\u33d1\0\u0239\6\u04c7\0\105\6\13\0\1\6\56\7\20\0\4\7\15\6" - + "\u4060\0\2\6\u2163\0\5\7\3\0\26\7\2\0\7\7\36\0\4\7" - + "\224\0\3\7\u01bb\0\125\6\1\0\107\6\1\0\2\6\2\0\1\6" - + "\2\0\2\6\2\0\4\6\1\0\14\6\1\0\1\6\1\0\7\6" - + "\1\0\101\6\1\0\4\6\2\0\10\6\1\0\7\6\1\0\34\6" - + "\1\0\4\6\1\0\5\6\1\0\1\6\3\0\7\6\1\0\u0154\6" - + "\2\0\31\6\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6" - + "\1\0\31\6\1\0\37\6\1\0\31\6\1\0\37\6\1\0\31\6" - + "\1\0\10\6\2\0\62\7\u1600\0\4\6\1\0\33\6\1\0\2\6" - + "\1\0\1\6\2\0\1\6\1\0\12\6\1\0\4\6\1\0\1\6" - + "\1\0\1\6\6\0\1\6\4\0\1\6\1\0\1\6\1\0\1\6" - + "\1\0\3\6\1\0\2\6\1\0\1\6\2\0\1\6\1\0\1\6" - + "\1\0\1\6\1\0\1\6\1\0\1\6\1\0\2\6\1\0\1\6" - + "\2\0\4\6\1\0\7\6\1\0\4\6\1\0\4\6\1\0\1\6" - + "\1\0\12\6\1\0\21\6\5\0\3\6\1\0\5\6\1\0\21\6" - + "\u1144\0\ua6d7\6\51\0\u1035\6\13\0\336\6\u3fe2\0\u021e\6\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\u05ee\0" - + "\1\7\36\0\140\7\200\0\360\7\uffff\0\uffff\0\ufe12\0"; - - /** - * Translates characters to character classes - */ - private static final char[] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int[] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 - = "\6\0\1\1\2\2\1\3\1\4\1\5\1\6\1\7" - + "\1\10\1\11\1\12\1\13\1\14\2\15\1\16\1\17" - + "\1\20\26\6\1\21\1\22\1\23\1\24\1\25\1\26" - + "\1\27\1\30\1\31\1\32\1\33\1\34\1\35\1\36" - + "\1\37\1\40\1\41\1\42\2\43\1\44\1\1\1\42" - + "\1\1\2\45\1\42\1\1\1\46\2\42\2\47\2\42" - + "\1\1\1\50\1\3\1\0\1\51\1\52\1\53\2\0" - + "\1\54\1\0\1\55\1\56\1\57\1\60\1\61\1\62" - + "\1\63\1\54\1\0\2\63\1\0\1\64\1\65\7\6" - + "\1\66\11\6\1\67\12\6\1\70\1\71\1\72\4\6" - + "\1\73\30\6\1\56\1\74\1\75\1\76\1\77\1\100" - + "\1\101\1\102\1\103\1\104\1\105\1\104\1\106\1\107" - + "\1\110\1\111\1\112\1\113\1\104\1\114\1\104\6\0" - + "\1\115\1\116\2\115\2\3\2\0\1\117\3\0\1\120" - + "\1\0\1\121\1\122\1\123\1\124\2\125\1\63\1\54" - + "\1\0\10\6\1\126\5\6\1\127\1\130\5\6\1\131" - + "\1\6\1\132\5\6\1\133\7\6\1\134\2\6\1\135" - + "\10\6\1\136\20\6\1\137\1\6\1\140\2\6\1\141" - + "\2\6\1\142\12\0\1\143\5\0\1\144\1\125\1\63" - + "\4\6\1\145\1\146\1\147\1\6\1\150\1\6\1\151" - + "\5\6\1\152\7\6\1\153\1\6\1\154\4\6\1\155" - + "\22\6\1\156\7\6\1\157\4\6\1\160\7\6\1\161" - + "\1\0\1\162\1\42\1\0\1\163\12\0\1\125\1\63" - + "\1\164\4\6\1\165\1\166\1\6\1\167\5\6\1\170" - + "\5\6\1\171\3\6\1\172\14\6\1\173\6\6\1\174" - + "\2\6\1\175\3\6\1\176\1\6\1\177\10\6\10\0" - + "\1\125\1\63\1\200\1\6\1\201\3\6\1\202\2\6" - + "\1\203\1\204\7\6\1\205\4\6\1\206\4\6\1\207" - + "\5\6\1\210\10\6\1\211\2\6\1\212\3\6\1\213" - + "\1\214\1\6\2\0\1\120\1\125\1\63\1\6\1\215" - + "\5\6\1\216\14\6\1\217\1\6\1\220\1\6\1\221" - + "\7\6\1\222\1\223\6\6\1\42\1\125\1\63\1\6" - + "\1\224\2\6\1\225\1\226\6\6\1\227\7\6\1\230" - + "\5\6\1\231\1\6\1\232\1\233\3\6\1\234\1\125" - + "\1\63\1\6\1\235\1\6\1\236\1\237\4\6\1\240" - + "\2\6\1\241\2\6\1\242\1\243\1\6\1\244\1\245" - + "\5\6\1\125\1\63\2\6\1\246\1\247\1\6\1\250" - + "\1\6\1\251\6\6\1\252\2\6\1\63\4\6\1\253" - + "\4\6\1\254\1\255\1\256\1\63\6\6\1\257\2\6" - + "\1\63\1\6\1\260\1\6\1\261\2\6\1\262\1\263" - + "\1\63\2\6\1\264\3\6\1\63\1\265\4\6\1\63" - + "\2\6\1\266\1\267\1\270\1\6\1\271"; - - private static int[] zzUnpackAction() { - int[] result = new int[705]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); } + return j; + } - private static int zzUnpackAction(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do { - result[j++] = value; - } while (--count > 0); - } - return j; + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\124\0\250\0\374\0\u0150\0\u01a4\0\u01f8\0\u024c"+ + "\0\u01f8\0\u02a0\0\u02f4\0\u0348\0\u039c\0\u03f0\0\u0444\0\u0498"+ + "\0\u04ec\0\u0540\0\u01f8\0\u0594\0\u05e8\0\u063c\0\u01f8\0\u0690"+ + "\0\u06e4\0\u0738\0\u078c\0\u07e0\0\u0834\0\u0888\0\u08dc\0\u0930"+ + "\0\u0984\0\u09d8\0\u0a2c\0\u0a80\0\u0ad4\0\u0b28\0\u0b7c\0\u0bd0"+ + "\0\u0c24\0\u0c78\0\u0ccc\0\u0d20\0\u0d74\0\u0dc8\0\u01f8\0\u01f8"+ + "\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u0e1c\0\u01f8"+ + "\0\u01f8\0\u0e70\0\u0ec4\0\u0f18\0\u0f6c\0\u0fc0\0\u01f8\0\u1014"+ + "\0\u1068\0\u01f8\0\u01f8\0\u10bc\0\u1110\0\u1164\0\u11b8\0\u01f8"+ + "\0\u120c\0\u1260\0\u01f8\0\u12b4\0\u01f8\0\u1308\0\u01f8\0\u135c"+ + "\0\u13b0\0\u1404\0\u01f8\0\u1458\0\u14ac\0\u01f8\0\u01f8\0\u01f8"+ + "\0\u1500\0\u1554\0\u15a8\0\u15fc\0\u1650\0\u01f8\0\u01f8\0\u16a4"+ + "\0\u01f8\0\u16f8\0\u174c\0\u17a0\0\u17f4\0\u1848\0\u189c\0\u18f0"+ + "\0\u01f8\0\u01f8\0\u1944\0\u1998\0\u19ec\0\u1a40\0\u1a94\0\u1ae8"+ + "\0\u1b3c\0\u1b90\0\u039c\0\u1be4\0\u1c38\0\u1c8c\0\u1ce0\0\u1d34"+ + "\0\u1d88\0\u1ddc\0\u1e30\0\u1e84\0\u1ed8\0\u1f2c\0\u1f80\0\u1fd4"+ + "\0\u2028\0\u207c\0\u20d0\0\u2124\0\u2178\0\u21cc\0\u2220\0\u039c"+ + "\0\u2274\0\u22c8\0\u231c\0\u2370\0\u23c4\0\u2418\0\u039c\0\u246c"+ + "\0\u24c0\0\u2514\0\u2568\0\u25bc\0\u2610\0\u2664\0\u26b8\0\u270c"+ + "\0\u2760\0\u27b4\0\u2808\0\u285c\0\u28b0\0\u2904\0\u2958\0\u29ac"+ + "\0\u2a00\0\u2a54\0\u2aa8\0\u2afc\0\u2b50\0\u2ba4\0\u2bf8\0\u2c4c"+ + "\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8"+ + "\0\u01f8\0\u01f8\0\u2ca0\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8"+ + "\0\u01f8\0\u2cf4\0\u01f8\0\u2d48\0\u1260\0\u2d9c\0\u2df0\0\u2e44"+ + "\0\u2e98\0\u2eec\0\u01f8\0\u01f8\0\u2cf4\0\u2d48\0\u2f40\0\u01f8"+ + "\0\u2f94\0\u2fe8\0\u01f8\0\u303c\0\u3090\0\u30e4\0\u01f8\0\u3138"+ + "\0\u01f8\0\u318c\0\u01f8\0\u01f8\0\u17f4\0\u31e0\0\u3234\0\u3288"+ + "\0\u3288\0\u32dc\0\u3330\0\u3384\0\u33d8\0\u342c\0\u3480\0\u34d4"+ + "\0\u3528\0\u357c\0\u039c\0\u35d0\0\u3624\0\u3678\0\u36cc\0\u3720"+ + "\0\u039c\0\u039c\0\u3774\0\u37c8\0\u381c\0\u3870\0\u38c4\0\u039c"+ + "\0\u3918\0\u396c\0\u39c0\0\u3a14\0\u3a68\0\u3abc\0\u3b10\0\u039c"+ + "\0\u3b64\0\u3bb8\0\u3c0c\0\u3c60\0\u3cb4\0\u3d08\0\u3d5c\0\u3db0"+ + "\0\u3e04\0\u3e58\0\u039c\0\u3eac\0\u3f00\0\u3f54\0\u3fa8\0\u3ffc"+ + "\0\u4050\0\u40a4\0\u40f8\0\u039c\0\u414c\0\u41a0\0\u41f4\0\u4248"+ + "\0\u429c\0\u42f0\0\u4344\0\u4398\0\u43ec\0\u4440\0\u4494\0\u44e8"+ + "\0\u453c\0\u4590\0\u45e4\0\u4638\0\u039c\0\u468c\0\u46e0\0\u4734"+ + "\0\u4788\0\u039c\0\u47dc\0\u4830\0\u01f8\0\u4884\0\u48d8\0\u492c"+ + "\0\u4980\0\u49d4\0\u4a28\0\u4a7c\0\u4ad0\0\u4b24\0\u4b78\0\u01f8"+ + "\0\u4bcc\0\u4c20\0\u4c74\0\u4cc8\0\u4d1c\0\u01f8\0\u4d70\0\u4dc4"+ + "\0\u4e18\0\u4e6c\0\u4ec0\0\u4f14\0\u039c\0\u039c\0\u039c\0\u4f68"+ + "\0\u039c\0\u4fbc\0\u039c\0\u5010\0\u5064\0\u50b8\0\u510c\0\u5160"+ + "\0\u51b4\0\u5208\0\u525c\0\u52b0\0\u5304\0\u5358\0\u53ac\0\u5400"+ + "\0\u039c\0\u5454\0\u039c\0\u54a8\0\u54fc\0\u5550\0\u55a4\0\u039c"+ + "\0\u55f8\0\u564c\0\u56a0\0\u56f4\0\u5748\0\u579c\0\u57f0\0\u5844"+ + "\0\u5898\0\u58ec\0\u5940\0\u5994\0\u59e8\0\u5a3c\0\u5a90\0\u5ae4"+ + "\0\u5b38\0\u5b8c\0\u039c\0\u5be0\0\u5c34\0\u5c88\0\u5cdc\0\u5d30"+ + "\0\u5d84\0\u5dd8\0\u039c\0\u5e2c\0\u5e80\0\u5ed4\0\u5f28\0\u039c"+ + "\0\u5f7c\0\u5fd0\0\u6024\0\u6078\0\u60cc\0\u6120\0\u6174\0\u01f8"+ + "\0\u2d48\0\u01f8\0\u61c8\0\u621c\0\u01f8\0\u6270\0\u62c4\0\u6318"+ + "\0\u636c\0\u63c0\0\u6414\0\u6468\0\u64bc\0\u6510\0\u6564\0\u65b8"+ + "\0\u660c\0\u039c\0\u6660\0\u66b4\0\u6708\0\u675c\0\u039c\0\u039c"+ + "\0\u67b0\0\u039c\0\u6804\0\u6858\0\u68ac\0\u6900\0\u6954\0\u039c"+ + "\0\u69a8\0\u69fc\0\u6a50\0\u6aa4\0\u6af8\0\u039c\0\u6b4c\0\u6ba0"+ + "\0\u6bf4\0\u039c\0\u6c48\0\u6c9c\0\u6cf0\0\u6d44\0\u6d98\0\u6dec"+ + "\0\u6e40\0\u6e94\0\u6ee8\0\u6f3c\0\u6f90\0\u6fe4\0\u039c\0\u7038"+ + "\0\u708c\0\u70e0\0\u7134\0\u7188\0\u71dc\0\u039c\0\u7230\0\u7284"+ + "\0\u72d8\0\u732c\0\u7380\0\u73d4\0\u039c\0\u7428\0\u039c\0\u747c"+ + "\0\u74d0\0\u7524\0\u7578\0\u75cc\0\u7620\0\u7674\0\u76c8\0\u771c"+ + "\0\u7770\0\u77c4\0\u7818\0\u786c\0\u78c0\0\u7914\0\u7968\0\u79bc"+ + "\0\u7a10\0\u039c\0\u7a64\0\u039c\0\u7ab8\0\u7b0c\0\u7b60\0\u039c"+ + "\0\u7bb4\0\u7c08\0\u039c\0\u039c\0\u7c5c\0\u7cb0\0\u7d04\0\u7d58"+ + "\0\u7dac\0\u7e00\0\u7e54\0\u039c\0\u7ea8\0\u7efc\0\u7f50\0\u7fa4"+ + "\0\u039c\0\u7ff8\0\u804c\0\u80a0\0\u80f4\0\u039c\0\u8148\0\u819c"+ + "\0\u81f0\0\u8244\0\u8298\0\u039c\0\u82ec\0\u8340\0\u8394\0\u83e8"+ + "\0\u843c\0\u8490\0\u84e4\0\u8538\0\u039c\0\u858c\0\u85e0\0\u039c"+ + "\0\u8634\0\u8688\0\u86dc\0\u039c\0\u039c\0\u8730\0\u8784\0\u87d8"+ + "\0\u6468\0\u882c\0\u8880\0\u88d4\0\u039c\0\u8928\0\u897c\0\u89d0"+ + "\0\u8a24\0\u8a78\0\u039c\0\u8acc\0\u8b20\0\u8b74\0\u8bc8\0\u8c1c"+ + "\0\u8c70\0\u8cc4\0\u8d18\0\u8d6c\0\u8dc0\0\u8e14\0\u8e68\0\u039c"+ + "\0\u8ebc\0\u039c\0\u8f10\0\u039c\0\u8f64\0\u8fb8\0\u900c\0\u9060"+ + "\0\u90b4\0\u9108\0\u915c\0\u039c\0\u039c\0\u91b0\0\u9204\0\u9258"+ + "\0\u92ac\0\u9300\0\u9354\0\u77c4\0\u93a8\0\u93fc\0\u9450\0\u039c"+ + "\0\u94a4\0\u94f8\0\u039c\0\u039c\0\u954c\0\u95a0\0\u95f4\0\u9648"+ + "\0\u969c\0\u96f0\0\u039c\0\u9744\0\u9798\0\u97ec\0\u9840\0\u9894"+ + "\0\u98e8\0\u993c\0\u039c\0\u9990\0\u99e4\0\u9a38\0\u9a8c\0\u9ae0"+ + "\0\u039c\0\u9b34\0\u039c\0\u039c\0\u9b88\0\u9bdc\0\u9c30\0\u039c"+ + "\0\u9c84\0\u9cd8\0\u9d2c\0\u039c\0\u9d80\0\u039c\0\u039c\0\u9dd4"+ + "\0\u9e28\0\u9e7c\0\u9ed0\0\u039c\0\u9f24\0\u9f78\0\u039c\0\u9fcc"+ + "\0\ua020\0\u039c\0\ua074\0\ua0c8\0\u039c\0\u039c\0\ua11c\0\ua170"+ + "\0\ua1c4\0\ua218\0\ua26c\0\u01f8\0\ua2c0\0\ua314\0\ua368\0\u039c"+ + "\0\u039c\0\ua3bc\0\u039c\0\ua410\0\u039c\0\ua464\0\ua4b8\0\ua50c"+ + "\0\ua560\0\ua5b4\0\ua608\0\u039c\0\ua65c\0\ua6b0\0\ua704\0\ua758"+ + "\0\ua7ac\0\ua800\0\ua854\0\ua8a8\0\ua8fc\0\ua950\0\ua9a4\0\ua9f8"+ + "\0\u039c\0\u039c\0\u039c\0\uaa4c\0\uaaa0\0\uaaf4\0\uab48\0\uab9c"+ + "\0\uabf0\0\uac44\0\u039c\0\uac98\0\uacec\0\uad40\0\uad94\0\u039c"+ + "\0\uade8\0\u039c\0\uae3c\0\uae90\0\uaee4\0\uaf38\0\uaf8c\0\uafe0"+ + "\0\ub034\0\u039c\0\ub088\0\ub0dc\0\ub130\0\ub184\0\u039c\0\ub1d8"+ + "\0\ub22c\0\ub280\0\ub2d4\0\u17a0\0\ub328\0\ub37c\0\u039c\0\u039c"+ + "\0\u039c\0\ub3d0\0\u039c"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[707]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); } + return j; + } - /** - * Translates a state to a row index in the transition table - */ - private static final int[] ZZ_ROWMAP = zzUnpackRowMap(); + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); - private static final String ZZ_ROWMAP_PACKED_0 - = "\0\0\0\124\0\250\0\374\0\u0150\0\u01a4\0\u01f8\0\u024c" - + "\0\u01f8\0\u02a0\0\u02f4\0\u0348\0\u039c\0\u03f0\0\u0444\0\u0498" - + "\0\u04ec\0\u0540\0\u01f8\0\u0594\0\u05e8\0\u063c\0\u01f8\0\u01f8" - + "\0\u0690\0\u06e4\0\u0738\0\u078c\0\u07e0\0\u0834\0\u0888\0\u08dc" - + "\0\u0930\0\u0984\0\u09d8\0\u0a2c\0\u0a80\0\u0ad4\0\u0b28\0\u0b7c" - + "\0\u0bd0\0\u0c24\0\u0c78\0\u0ccc\0\u0d20\0\u0d74\0\u01f8\0\u01f8" - + "\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u0dc8\0\u01f8" - + "\0\u01f8\0\u0e1c\0\u0e70\0\u0ec4\0\u0f18\0\u0f6c\0\u01f8\0\u0fc0" - + "\0\u1014\0\u01f8\0\u01f8\0\u1068\0\u10bc\0\u1110\0\u1164\0\u01f8" - + "\0\u11b8\0\u120c\0\u01f8\0\u1260\0\u01f8\0\u12b4\0\u01f8\0\u1308" - + "\0\u135c\0\u13b0\0\u01f8\0\u1404\0\u1458\0\u01f8\0\u01f8\0\u01f8" - + "\0\u14ac\0\u1500\0\u1554\0\u15a8\0\u15fc\0\u01f8\0\u01f8\0\u1650" - + "\0\u01f8\0\u16a4\0\u16f8\0\u174c\0\u17a0\0\u17f4\0\u1848\0\u189c" - + "\0\u01f8\0\u01f8\0\u18f0\0\u1944\0\u1998\0\u19ec\0\u1a40\0\u1a94" - + "\0\u1ae8\0\u039c\0\u1b3c\0\u1b90\0\u1be4\0\u1c38\0\u1c8c\0\u1ce0" - + "\0\u1d34\0\u1d88\0\u1ddc\0\u1e30\0\u1e84\0\u1ed8\0\u1f2c\0\u1f80" - + "\0\u1fd4\0\u2028\0\u207c\0\u20d0\0\u2124\0\u2178\0\u039c\0\u21cc" - + "\0\u2220\0\u2274\0\u22c8\0\u231c\0\u2370\0\u039c\0\u23c4\0\u2418" - + "\0\u246c\0\u24c0\0\u2514\0\u2568\0\u25bc\0\u2610\0\u2664\0\u26b8" - + "\0\u270c\0\u2760\0\u27b4\0\u2808\0\u285c\0\u28b0\0\u2904\0\u2958" - + "\0\u29ac\0\u2a00\0\u2a54\0\u2aa8\0\u2afc\0\u2b50\0\u2ba4\0\u01f8" - + "\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8" - + "\0\u01f8\0\u2bf8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8\0\u01f8" - + "\0\u2c4c\0\u01f8\0\u2ca0\0\u120c\0\u2cf4\0\u2d48\0\u2d9c\0\u2df0" - + "\0\u2e44\0\u01f8\0\u01f8\0\u2c4c\0\u2ca0\0\u2e98\0\u01f8\0\u2eec" - + "\0\u2f40\0\u01f8\0\u2f94\0\u2fe8\0\u303c\0\u01f8\0\u3090\0\u01f8" - + "\0\u30e4\0\u01f8\0\u01f8\0\u17a0\0\u3138\0\u318c\0\u31e0\0\u31e0" - + "\0\u3234\0\u3288\0\u32dc\0\u3330\0\u3384\0\u33d8\0\u342c\0\u3480" - + "\0\u039c\0\u34d4\0\u3528\0\u357c\0\u35d0\0\u3624\0\u039c\0\u039c" - + "\0\u3678\0\u36cc\0\u3720\0\u3774\0\u37c8\0\u039c\0\u381c\0\u3870" - + "\0\u38c4\0\u3918\0\u396c\0\u39c0\0\u3a14\0\u039c\0\u3a68\0\u3abc" - + "\0\u3b10\0\u3b64\0\u3bb8\0\u3c0c\0\u3c60\0\u3cb4\0\u3d08\0\u3d5c" - + "\0\u039c\0\u3db0\0\u3e04\0\u3e58\0\u3eac\0\u3f00\0\u3f54\0\u3fa8" - + "\0\u3ffc\0\u039c\0\u4050\0\u40a4\0\u40f8\0\u414c\0\u41a0\0\u41f4" - + "\0\u4248\0\u429c\0\u42f0\0\u4344\0\u4398\0\u43ec\0\u4440\0\u4494" - + "\0\u44e8\0\u453c\0\u039c\0\u4590\0\u45e4\0\u4638\0\u468c\0\u039c" - + "\0\u46e0\0\u4734\0\u01f8\0\u4788\0\u47dc\0\u4830\0\u4884\0\u48d8" - + "\0\u492c\0\u4980\0\u49d4\0\u4a28\0\u4a7c\0\u01f8\0\u4ad0\0\u4b24" - + "\0\u4b78\0\u4bcc\0\u4c20\0\u01f8\0\u4c74\0\u4cc8\0\u4d1c\0\u4d70" - + "\0\u4dc4\0\u4e18\0\u039c\0\u039c\0\u039c\0\u4e6c\0\u039c\0\u4ec0" - + "\0\u039c\0\u4f14\0\u4f68\0\u4fbc\0\u5010\0\u5064\0\u50b8\0\u510c" - + "\0\u5160\0\u51b4\0\u5208\0\u525c\0\u52b0\0\u5304\0\u039c\0\u5358" - + "\0\u039c\0\u53ac\0\u5400\0\u5454\0\u54a8\0\u039c\0\u54fc\0\u5550" - + "\0\u55a4\0\u55f8\0\u564c\0\u56a0\0\u56f4\0\u5748\0\u579c\0\u57f0" - + "\0\u5844\0\u5898\0\u58ec\0\u5940\0\u5994\0\u59e8\0\u5a3c\0\u5a90" - + "\0\u039c\0\u5ae4\0\u5b38\0\u5b8c\0\u5be0\0\u5c34\0\u5c88\0\u5cdc" - + "\0\u039c\0\u5d30\0\u5d84\0\u5dd8\0\u5e2c\0\u039c\0\u5e80\0\u5ed4" - + "\0\u5f28\0\u5f7c\0\u5fd0\0\u6024\0\u6078\0\u01f8\0\u2ca0\0\u01f8" - + "\0\u60cc\0\u6120\0\u01f8\0\u6174\0\u61c8\0\u621c\0\u6270\0\u62c4" - + "\0\u6318\0\u636c\0\u63c0\0\u6414\0\u6468\0\u64bc\0\u6510\0\u039c" - + "\0\u6564\0\u65b8\0\u660c\0\u6660\0\u039c\0\u039c\0\u66b4\0\u039c" - + "\0\u6708\0\u675c\0\u67b0\0\u6804\0\u6858\0\u039c\0\u68ac\0\u6900" - + "\0\u6954\0\u69a8\0\u69fc\0\u039c\0\u6a50\0\u6aa4\0\u6af8\0\u039c" - + "\0\u6b4c\0\u6ba0\0\u6bf4\0\u6c48\0\u6c9c\0\u6cf0\0\u6d44\0\u6d98" - + "\0\u6dec\0\u6e40\0\u6e94\0\u6ee8\0\u039c\0\u6f3c\0\u6f90\0\u6fe4" - + "\0\u7038\0\u708c\0\u70e0\0\u039c\0\u7134\0\u7188\0\u71dc\0\u7230" - + "\0\u7284\0\u72d8\0\u039c\0\u732c\0\u039c\0\u7380\0\u73d4\0\u7428" - + "\0\u747c\0\u74d0\0\u7524\0\u7578\0\u75cc\0\u7620\0\u7674\0\u76c8" - + "\0\u771c\0\u7770\0\u77c4\0\u7818\0\u786c\0\u78c0\0\u7914\0\u039c" - + "\0\u7968\0\u039c\0\u79bc\0\u7a10\0\u7a64\0\u039c\0\u7ab8\0\u7b0c" - + "\0\u039c\0\u039c\0\u7b60\0\u7bb4\0\u7c08\0\u7c5c\0\u7cb0\0\u7d04" - + "\0\u7d58\0\u039c\0\u7dac\0\u7e00\0\u7e54\0\u7ea8\0\u039c\0\u7efc" - + "\0\u7f50\0\u7fa4\0\u7ff8\0\u039c\0\u804c\0\u80a0\0\u80f4\0\u8148" - + "\0\u819c\0\u039c\0\u81f0\0\u8244\0\u8298\0\u82ec\0\u8340\0\u8394" - + "\0\u83e8\0\u843c\0\u039c\0\u8490\0\u84e4\0\u039c\0\u8538\0\u858c" - + "\0\u85e0\0\u039c\0\u039c\0\u8634\0\u8688\0\u86dc\0\u636c\0\u8730" - + "\0\u8784\0\u87d8\0\u039c\0\u882c\0\u8880\0\u88d4\0\u8928\0\u897c" - + "\0\u039c\0\u89d0\0\u8a24\0\u8a78\0\u8acc\0\u8b20\0\u8b74\0\u8bc8" - + "\0\u8c1c\0\u8c70\0\u8cc4\0\u8d18\0\u8d6c\0\u039c\0\u8dc0\0\u039c" - + "\0\u8e14\0\u039c\0\u8e68\0\u8ebc\0\u8f10\0\u8f64\0\u8fb8\0\u900c" - + "\0\u9060\0\u039c\0\u039c\0\u90b4\0\u9108\0\u915c\0\u91b0\0\u9204" - + "\0\u9258\0\u76c8\0\u92ac\0\u9300\0\u9354\0\u039c\0\u93a8\0\u93fc" - + "\0\u039c\0\u039c\0\u9450\0\u94a4\0\u94f8\0\u954c\0\u95a0\0\u95f4" - + "\0\u039c\0\u9648\0\u969c\0\u96f0\0\u9744\0\u9798\0\u97ec\0\u9840" - + "\0\u039c\0\u9894\0\u98e8\0\u993c\0\u9990\0\u99e4\0\u039c\0\u9a38" - + "\0\u039c\0\u039c\0\u9a8c\0\u9ae0\0\u9b34\0\u039c\0\u9b88\0\u9bdc" - + "\0\u9c30\0\u039c\0\u9c84\0\u039c\0\u039c\0\u9cd8\0\u9d2c\0\u9d80" - + "\0\u9dd4\0\u039c\0\u9e28\0\u9e7c\0\u039c\0\u9ed0\0\u9f24\0\u039c" - + "\0\u9f78\0\u9fcc\0\u039c\0\u039c\0\ua020\0\ua074\0\ua0c8\0\ua11c" - + "\0\ua170\0\u01f8\0\ua1c4\0\ua218\0\ua26c\0\u039c\0\u039c\0\ua2c0" - + "\0\u039c\0\ua314\0\u039c\0\ua368\0\ua3bc\0\ua410\0\ua464\0\ua4b8" - + "\0\ua50c\0\u039c\0\ua560\0\ua5b4\0\ua608\0\ua65c\0\ua6b0\0\ua704" - + "\0\ua758\0\ua7ac\0\ua800\0\ua854\0\ua8a8\0\ua8fc\0\u039c\0\u039c" - + "\0\u039c\0\ua950\0\ua9a4\0\ua9f8\0\uaa4c\0\uaaa0\0\uaaf4\0\uab48" - + "\0\u039c\0\uab9c\0\uabf0\0\uac44\0\uac98\0\u039c\0\uacec\0\u039c" - + "\0\uad40\0\uad94\0\uade8\0\uae3c\0\uae90\0\uaee4\0\uaf38\0\u039c" - + "\0\uaf8c\0\uafe0\0\ub034\0\ub088\0\u039c\0\ub0dc\0\ub130\0\ub184" - + "\0\ub1d8\0\u174c\0\ub22c\0\ub280\0\u039c\0\u039c\0\u039c\0\ub2d4" - + "\0\u039c"; + private static final String ZZ_TRANS_PACKED_0 = + "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\7"+ + "\1\16\1\17\1\20\1\21\1\12\1\22\1\23\1\24"+ + "\1\25\2\15\2\25\1\15\1\26\1\7\1\27\1\30"+ + "\1\31\1\32\1\33\1\34\1\15\1\35\1\36\1\37"+ + "\1\40\1\41\1\42\1\43\1\44\1\45\1\46\1\47"+ + "\1\15\1\50\1\15\1\51\1\52\1\15\1\53\2\15"+ + "\1\54\12\15\1\55\1\56\1\57\1\60\1\61\1\62"+ + "\1\63\1\64\1\65\1\66\1\67\1\70\1\71\1\72"+ + "\1\73\1\74\1\75\1\76\1\77\1\7\1\12\1\7"+ + "\1\100\1\101\1\102\13\100\1\103\10\100\1\104\74\100"+ + "\1\105\1\101\1\102\24\105\1\106\1\103\73\105\1\7"+ + "\1\107\1\110\1\111\2\7\1\112\4\7\1\113\1\114"+ + "\4\7\2\112\2\7\1\112\4\7\46\112\22\7\1\111"+ + "\1\7\1\115\1\116\1\117\7\115\1\120\111\115\1\121"+ + "\1\101\1\102\24\121\1\122\1\121\1\123\72\121\126\0"+ + "\1\11\124\0\1\12\10\0\1\12\105\0\1\12\5\0"+ + "\1\124\1\125\7\0\1\126\123\0\1\127\114\0\2\15"+ + "\7\0\7\15\4\0\46\15\23\0\1\15\10\0\1\130"+ + "\124\0\1\131\1\132\4\0\2\133\2\0\2\133\105\0"+ + "\1\134\3\0\1\135\1\136\1\0\1\137\3\0\2\134"+ + "\2\0\1\134\4\0\46\134\37\0\1\140\1\0\1\141"+ + "\123\0\1\142\117\0\1\133\5\0\1\143\1\144\1\145"+ + "\1\0\1\146\1\147\1\150\6\0\1\150\22\0\1\145"+ + "\55\0\1\133\5\0\2\25\2\0\2\25\1\150\6\0"+ + "\1\150\104\0\1\151\10\0\1\152\126\0\1\153\100\0"+ + "\2\15\7\0\7\15\4\0\1\15\1\154\44\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\155"+ + "\1\156\42\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\3\15\1\157\12\15\1\160\5\15\1\161\1\162"+ + "\20\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\163\1\15\1\164\35\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\165\3\15\1\166"+ + "\6\15\1\167\1\15\1\170\25\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\171\6\15\1\172"+ + "\1\15\1\173\3\15\1\174\26\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\15\1\175\22\15\1\176"+ + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\177\1\200\7\15\1\201\32\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\1\15\1\202\1\203"+ + "\1\204\3\15\1\205\10\15\1\206\1\15\1\207\23\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\6\15"+ + "\1\210\1\15\1\211\4\15\1\212\5\15\1\213\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\6\15"+ + "\1\214\1\15\1\215\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\216\4\15\1\217\3\15"+ + "\1\220\6\15\1\221\23\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\222\2\15\1\223\1\224"+ + "\2\15\1\225\1\226\32\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\227\4\15\1\230\36\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\231\5\15\1\232\25\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\233\1\15\1\234\7\15"+ + "\1\235\2\15\1\236\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\237\45\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\240\3\15\1\241"+ + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\242\4\15\1\243\36\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\244\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\245"+ + "\7\15\1\246\32\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\10\15\1\247\35\15\23\0\1\15\15\0"+ + "\1\250\123\0\1\251\75\0\1\252\25\0\1\253\76\0"+ + "\1\254\24\0\1\255\77\0\1\256\23\0\1\257\123\0"+ + "\1\260\106\0\1\100\2\0\13\100\1\0\10\100\1\0"+ + "\74\100\2\0\1\102\121\0\1\261\2\0\13\261\1\262"+ + "\1\263\3\261\2\263\2\261\1\264\1\265\1\261\1\266"+ + "\1\267\6\261\1\270\1\271\1\261\1\272\1\261\1\273"+ + "\7\261\1\274\41\261\3\0\1\105\2\0\24\105\2\0"+ + "\73\105\1\261\2\0\13\261\1\262\10\261\1\264\1\265"+ + "\1\261\1\266\1\267\6\261\1\270\1\271\1\261\1\272"+ + "\1\261\1\273\7\261\1\274\41\261\5\0\1\110\124\0"+ + "\1\111\10\0\1\111\105\0\1\111\7\0\2\275\1\276"+ + "\3\0\1\277\1\300\1\0\7\275\4\0\46\275\23\0"+ + "\1\275\3\0\1\111\2\0\1\275\5\0\1\114\4\0"+ + "\2\275\2\0\1\275\4\0\46\275\22\0\1\111\3\0"+ + "\1\117\125\0\1\301\1\0\1\302\12\0\2\302\2\0"+ + "\1\302\4\0\46\302\24\0\1\121\2\0\24\121\1\0"+ + "\1\121\1\0\72\121\1\303\2\0\24\303\1\264\1\303"+ + "\1\304\1\266\1\267\6\303\1\270\1\271\1\303\1\305"+ + "\1\303\1\273\7\303\1\306\41\303\3\0\1\124\1\307"+ + "\1\310\121\124\5\311\1\312\116\311\11\0\1\313\120\0"+ + "\1\314\12\0\2\314\2\0\1\314\4\0\46\314\43\0"+ + "\2\133\2\0\2\133\1\150\6\0\1\150\75\0\1\315"+ + "\1\134\1\316\2\0\1\317\1\320\2\0\2\134\2\315"+ + "\2\134\1\315\4\0\46\315\23\0\1\134\15\0\1\321"+ + "\121\0\1\322\1\0\1\323\123\0\1\324\117\0\1\133"+ + "\5\0\1\143\1\144\2\0\1\146\1\147\1\150\6\0"+ + "\1\150\100\0\1\133\5\0\2\144\2\0\2\144\1\150"+ + "\6\0\1\150\106\0\1\325\1\326\1\0\4\326\4\0"+ + "\1\326\1\0\2\326\1\0\1\326\6\0\2\326\12\0"+ + "\1\326\1\0\1\326\5\0\2\326\41\0\1\133\5\0"+ + "\1\147\1\144\2\0\2\147\1\150\6\0\1\150\100\0"+ + "\1\133\5\0\1\327\1\144\2\0\2\327\1\150\6\0"+ + "\1\150\106\0\2\330\2\0\2\330\1\0\1\331\66\0"+ + "\1\331\14\0\1\332\12\0\2\332\2\0\1\332\4\0"+ + "\46\332\32\0\2\15\7\0\7\15\4\0\2\15\1\333"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\334\11\15\1\335\22\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\10\15\1\336\35\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\5\15\1\337"+ + "\40\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\340\37\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\341\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\342\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\343"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\344\2\15\1\345\4\15\1\346\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\347"+ + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\350\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\15\1\351\44\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\352\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\353"+ + "\3\15\1\354\36\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\355\20\15\1\356\24\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\357\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\360\31\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\361\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\17\15\1\362\5\15\1\363\20\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15"+ + "\1\364\22\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\365\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\366\7\15\1\367\6\15"+ + "\1\370\23\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\371\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\372\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\26\15\1\373\17\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15"+ + "\1\374\10\15\1\375\33\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\21\15\1\376\24\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\6\15\1\377\2\15"+ + "\1\u0100\34\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\32\15\1\u0101\13\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\21\15\1\u0102\24\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0103\43\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\u0104\1\15\1\u0105\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\15\15\1\u0106\1\u0107\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\21\15\1\u0108"+ + "\24\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\10\15\1\u0109\35\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u010a\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\5\15\1\u010b\40\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u010c"+ + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\10\15\1\u010d\35\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\10\15\1\u010e\35\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\10\15\1\u010f\35\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0110"+ + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u0111\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u0112\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u0113\4\15\1\u0114"+ + "\2\15\1\u0115\33\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\5\15\1\u0116\40\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\u0117\45\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\3\15\1\u0118\42\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\5\15"+ + "\1\u0119\1\u011a\1\u011b\6\15\1\u011c\27\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\1\15\1\u011d\44\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\u011e\33\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\11\15\1\u011f\34\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\11\15\1\u0120\34\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\1\15\1\u0121\44\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\44\15"+ + "\1\u0122\1\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\23\15\1\u0123\22\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\15\15\1\u0124\30\15\23\0\1\15"+ + "\15\0\1\u0125\125\0\1\u0126\3\0\2\u0126\116\0\2\u0127"+ + "\1\0\4\u0127\4\0\1\u0127\1\0\2\u0127\1\0\1\u0127"+ + "\6\0\2\u0127\12\0\1\u0127\1\0\1\u0127\5\0\2\u0127"+ + "\47\0\2\u0128\1\0\4\u0128\4\0\1\u0128\1\0\2\u0128"+ + "\1\0\1\u0128\6\0\2\u0128\12\0\1\u0128\1\0\1\u0128"+ + "\5\0\2\u0128\36\0\1\u0129\12\0\2\u0129\2\0\1\u0129"+ + "\4\0\46\u0129\40\0\1\277\1\300\122\0\1\300\1\0"+ + "\1\u012a\113\0\1\u012b\12\0\2\u012b\2\0\1\u012b\4\0"+ + "\46\u012b\32\0\1\u012c\1\302\1\u012d\2\0\1\115\1\u012e"+ + "\2\0\2\302\2\u012c\2\302\1\u012c\4\0\46\u012c\23\0"+ + "\1\302\2\0\1\310\121\0\5\311\1\u012f\116\311\4\0"+ + "\1\310\1\312\124\0\2\314\3\0\1\u0130\3\0\7\314"+ + "\4\0\46\314\23\0\1\314\6\0\2\315\1\u0131\2\0"+ + "\1\317\1\u0132\1\u0133\1\0\7\315\4\0\46\315\23\0"+ + "\1\315\6\0\1\u0134\12\0\2\u0134\2\0\1\u0134\4\0"+ + "\46\u0134\32\0\1\u0135\5\0\1\320\4\0\2\u0135\2\0"+ + "\1\u0135\4\0\46\u0135\41\0\1\u0136\125\0\2\u0137\1\0"+ + "\4\u0137\4\0\1\u0137\1\0\2\u0137\1\0\1\u0137\6\0"+ + "\2\u0137\12\0\1\u0137\1\0\1\u0137\5\0\2\u0137\41\0"+ + "\1\133\5\0\1\u0138\1\144\2\0\2\u0138\1\150\6\0"+ + "\1\150\106\0\2\330\2\0\2\330\105\0\2\332\7\0"+ + "\7\332\4\0\46\332\23\0\1\332\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\u0139\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\13\15\1\u013a\32\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u013b"+ + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\14\15\1\u013c\31\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\20\15\1\u013d\25\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u013e\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u013f"+ + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u0140\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0141\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\5\15\1\u0142\40\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u0143"+ + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\u0144\2\15\1\u0145\34\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u0146\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u0147"+ + "\7\15\1\u0148\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\21\15\1\u0149\24\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u014a\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u014b"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u014c\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\15\1\u014d\44\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\16\15\1\u014e\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u014f"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u0150\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u0151\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\5\15\1\u0152\40\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u0153"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\16\15\1\u0154\27\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\26\15\1\u0155\17\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\26\15\1\u0156\17\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u0157"+ + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\6\15\1\u0158\37\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0159\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u015a\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u015b"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\1\15\1\u015c\44\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\7\15\1\u015d\6\15\1\u015e\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u015f"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\7\15\1\u0160\36\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\u0161\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u0162\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u0163"+ + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\u0164\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\6\15\1\u0165\37\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\7\15\1\u0166\36\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0167"+ + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\5\15\1\u0168\40\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\26\15\1\u0169\17\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\14\15\1\u016a\31\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\20\15\1\u016b"+ + "\25\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\16\15\1\u016c\27\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\24\15\1\u016d\21\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u016e\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u016f"+ + "\13\15\1\u0170\21\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\4\15\1\u0171\41\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\16\15\1\u0172\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\22\15\1\u0173"+ + "\23\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\20\15\1\u0174\25\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\13\15\1\u0175\32\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\15\1\u0176\44\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u0177"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\14\15\1\u0178\31\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\27\15\1\u0179\3\15\1\u017a\6\15\1\u017b"+ + "\3\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\7\15\1\u017c\36\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u017d\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\u017e\45\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u017f\33\15"+ + "\23\0\1\15\17\0\1\u0180\3\0\2\u0180\116\0\2\u0181"+ + "\1\0\4\u0181\4\0\1\u0181\1\0\2\u0181\1\0\1\u0181"+ + "\6\0\2\u0181\12\0\1\u0181\1\0\1\u0181\5\0\2\u0181"+ + "\47\0\2\u0182\1\0\4\u0182\4\0\1\u0182\1\0\2\u0182"+ + "\1\0\1\u0182\6\0\2\u0182\12\0\1\u0182\1\0\1\u0182"+ + "\5\0\2\u0182\36\0\2\u0129\4\0\1\277\1\300\1\0"+ + "\7\u0129\4\0\46\u0129\23\0\1\u0129\1\u012a\2\0\13\u012a"+ + "\1\u0183\105\u012a\6\0\2\u012b\1\u0184\2\0\1\u0185\3\0"+ + "\7\u012b\4\0\46\u012b\23\0\1\u012b\6\0\2\u012c\1\u0186"+ + "\2\0\1\115\1\u0187\1\u0188\1\0\7\u012c\4\0\46\u012c"+ + "\23\0\1\u012c\6\0\1\u0189\12\0\2\u0189\2\0\1\u0189"+ + "\4\0\46\u0189\32\0\1\u018a\5\0\1\u012e\4\0\2\u018a"+ + "\2\0\1\u018a\4\0\46\u018a\24\0\4\311\1\310\1\u012f"+ + "\116\311\6\0\1\u018b\12\0\2\u018b\2\0\1\u018b\4\0"+ + "\46\u018b\32\0\1\u0135\5\0\1\u0132\1\u0133\3\0\2\u0135"+ + "\2\0\1\u0135\4\0\46\u0135\40\0\1\u0133\1\0\1\u018c"+ + "\113\0\1\u018d\1\u0134\3\0\1\317\1\320\2\0\2\u0134"+ + "\2\u018d\2\u0134\1\u018d\4\0\46\u018d\23\0\1\u0134\6\0"+ + "\2\u0135\1\u018e\3\0\1\u018f\1\u0133\1\0\7\u0135\4\0"+ + "\46\u0135\23\0\1\u0135\17\0\2\u0190\1\0\4\u0190\4\0"+ + "\1\u0190\1\0\2\u0190\1\0\1\u0190\6\0\2\u0190\12\0"+ + "\1\u0190\1\0\1\u0190\5\0\2\u0190\41\0\1\133\5\0"+ + "\1\u0191\1\144\2\0\2\u0191\1\150\6\0\1\150\75\0"+ + "\2\15\7\0\7\15\4\0\4\15\1\u0192\41\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u0193"+ + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\24\15\1\u0194\21\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\7\15\1\u0195\36\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\10\15\1\u0196\35\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\20\15\1\u0197"+ + "\25\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u0198\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u0199\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u019a\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u019b"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\12\15\1\u019c\33\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\30\15\1\u019d\10\15\1\u019e\4\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u019f"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\1\15\1\u01a0\44\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\5\15\1\u01a1\40\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\15\1\u01a2\44\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\12\15\1\u01a3"+ + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\32\15\1\u01a4\13\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\6\15\1\u01a5\37\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u01a6\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\33\15\1\u01a7"+ + "\12\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u01a8\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u01a9\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\17\15\1\u01aa\26\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u01ab"+ + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\u01ac\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\15\1\u01ad\44\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u01ae\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u01af"+ + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u01b0\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\15\15\1\u01b1\30\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u01b2\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u01b3"+ + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u01b4\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u01b5\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\23\15\1\u01b6\22\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u01b7"+ + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\23\15\1\u01b8\22\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u01b9\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u01ba\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u01bb"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\37\15\1\u01bc\2\15\1\u01bd\3\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u01be\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\32\15\1\u01bf"+ + "\13\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u01c0\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\11\15\1\u01c1\34\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u01c2\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u01c3"+ + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\12\15\1\u01c4\33\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\1\15\1\u01c5\44\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\1\u01c6\45\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u01c7\31\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15"+ + "\1\u01c8\35\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\1\15\1\u01c9\44\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u01ca\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u01cb\43\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\30\15"+ + "\1\u01cc\15\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01cd\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u01ce\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u01cf\35\15"+ + "\23\0\1\15\1\u012a\2\0\11\u012a\1\u0183\1\u012a\1\u0183"+ + "\105\u012a\6\0\1\u01d0\12\0\2\u01d0\2\0\1\u01d0\4\0"+ + "\46\u01d0\32\0\1\u01d1\12\0\2\u01d1\2\0\1\u01d1\4\0"+ + "\46\u01d1\32\0\1\u018a\5\0\1\u0187\1\u0188\3\0\2\u018a"+ + "\2\0\1\u018a\4\0\46\u018a\40\0\1\u0188\1\0\1\u01d2"+ + "\113\0\1\u01d3\1\u0189\3\0\1\115\1\u012e\2\0\2\u0189"+ + "\2\u01d3\2\u0189\1\u01d3\4\0\46\u01d3\23\0\1\u0189\6\0"+ + "\2\u018a\1\u01d4\3\0\1\u01d5\1\u0188\1\0\7\u018a\4\0"+ + "\46\u018a\23\0\1\u018a\6\0\1\u018d\1\u018b\3\0\1\317"+ + "\1\u0132\1\u0133\1\0\2\u018b\2\u018d\2\u018b\1\u018d\4\0"+ + "\46\u018d\23\0\1\u018b\1\u018c\2\0\13\u018c\1\u01d6\105\u018c"+ + "\6\0\2\u018d\1\u018e\2\0\1\317\1\u0132\1\u0133\1\0"+ + "\7\u018d\4\0\46\u018d\23\0\1\u018d\6\0\1\u01d7\12\0"+ + "\2\u01d7\2\0\1\u01d7\4\0\46\u01d7\40\0\1\u018f\1\u0133"+ + "\125\0\2\u01d8\1\0\4\u01d8\4\0\1\u01d8\1\0\2\u01d8"+ + "\1\0\1\u01d8\6\0\2\u01d8\12\0\1\u01d8\1\0\1\u01d8"+ + "\5\0\2\u01d8\41\0\1\133\5\0\1\u01d9\1\144\2\0"+ + "\2\u01d9\1\150\6\0\1\150\75\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01da\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u01db\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u01dc\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\u01dd\31\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01de\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\41\15\1\u01df\4\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u01e0\40\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15"+ + "\1\u01e1\27\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\1\15\1\u01e2\44\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\u01e3\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\20\15\1\u01e4\25\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\u01e5\33\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01e6\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\u01e7\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\21\15\1\u01e8\24\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\3\15"+ + "\1\u01e9\42\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\11\15\1\u01ea\34\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u01eb\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\15\15\1\u01ec\30\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15"+ + "\1\u01ed\35\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u01ee\4\15\1\u01ef\30\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u01f0\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15"+ + "\1\u01f1\34\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\23\15\1\u01f2\22\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u01f3\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u01f4\31\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15"+ + "\1\u01f5\27\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u01f6\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\5\15\1\u01f7\40\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u01f8\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15"+ + "\1\u01f9\22\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\u01fa\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u01fb\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\20\15\1\u01fc\25\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\7\15"+ + "\1\u01fd\36\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\3\15\1\u01fe\42\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\u01ff\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u0200\40\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\30\15"+ + "\1\u0201\13\15\1\u0202\1\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\11\15\1\u0203\34\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\26\15\1\u0204\17\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\5\15"+ + "\1\u0205\40\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\6\15\1\u0206\37\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\26\15\1\u0207\17\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\16\15\1\u0208\27\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15"+ + "\1\u0209\22\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\1\15\1\u020a\44\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\10\15\1\u020b\35\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\26\15\1\u020c\17\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15"+ + "\1\u020d\44\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\12\15\1\u020e\33\15\23\0\1\15\6\0\2\u01d0"+ + "\3\0\1\u0185\3\0\7\u01d0\4\0\46\u01d0\23\0\1\u01d0"+ + "\6\0\1\u01d3\1\u01d1\3\0\1\115\1\u0187\1\u0188\1\0"+ + "\2\u01d1\2\u01d3\2\u01d1\1\u01d3\4\0\46\u01d3\23\0\1\u01d1"+ + "\1\u01d2\2\0\13\u01d2\1\u020f\105\u01d2\6\0\2\u01d3\1\u01d4"+ + "\2\0\1\115\1\u0187\1\u0188\1\0\7\u01d3\4\0\46\u01d3"+ + "\23\0\1\u01d3\6\0\1\u0210\12\0\2\u0210\2\0\1\u0210"+ + "\4\0\46\u0210\40\0\1\u01d5\1\u0188\106\0\1\u018c\2\0"+ + "\10\u018c\1\u0211\1\u01d6\1\u018c\1\u01d6\105\u018c\6\0\2\u01d7"+ + "\4\0\1\u018f\1\u0133\1\0\7\u01d7\4\0\46\u01d7\23\0"+ + "\1\u01d7\17\0\2\u0212\1\0\4\u0212\4\0\1\u0212\1\0"+ + "\2\u0212\1\0\1\u0212\6\0\2\u0212\12\0\1\u0212\1\0"+ + "\1\u0212\5\0\2\u0212\41\0\1\133\5\0\1\u0213\1\144"+ + "\2\0\2\u0213\1\150\6\0\1\150\75\0\2\15\7\0"+ + "\7\15\4\0\37\15\1\u0214\6\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u0215\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u0216"+ + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\1\15\1\u0217\44\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\16\15\1\u0218\27\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u0219\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u021a"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u021b\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\u021c\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u021d\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u021e"+ + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\43\15\1\u021f\2\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\34\15\1\u0220\11\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\5\15\1\u0221\40\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0222"+ + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\u0223\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0224\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u0225\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u0226"+ + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\37\15\1\u0227\6\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\11\15\1\u0228\34\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u0229\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\5\15\1\u022a"+ + "\40\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\3\15\1\u022b\42\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\22\15\1\u022c\23\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\7\15\1\u022d\36\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\24\15\1\u022e"+ + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\1\15\1\u022f\44\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\3\15\1\u0230\42\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u0231\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\u0232"+ + "\37\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\13\15\1\u0233\32\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0234\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\2\15\1\u0235\43\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u0236"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u0237\34\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0238\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u0239\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u023a"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\11\15\1\u023b\34\15\23\0\1\15\1\u01d2\2\0\10\u01d2"+ + "\1\u023c\1\u020f\1\u01d2\1\u020f\105\u01d2\6\0\2\u0210\4\0"+ + "\1\u01d5\1\u0188\1\0\7\u0210\4\0\46\u0210\23\0\1\u0210"+ + "\17\0\2\u023d\1\0\4\u023d\4\0\1\u023d\1\0\2\u023d"+ + "\1\0\1\u023d\6\0\2\u023d\12\0\1\u023d\1\0\1\u023d"+ + "\5\0\2\u023d\41\0\1\133\5\0\1\u023e\1\144\2\0"+ + "\2\u023e\1\150\6\0\1\150\75\0\2\15\7\0\7\15"+ + "\4\0\7\15\1\u023f\36\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u0240\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\3\15\1\u0241\42\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\31\15"+ + "\1\u0242\14\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\26\15\1\u0243\17\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u0244\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u0245\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\5\15"+ + "\1\u0246\40\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\26\15\1\u0247\17\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\u0248\42\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u0249\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15"+ + "\1\u024a\43\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\u024b\27\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\5\15\1\u024c\40\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\36\15\1\u024d\7\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15"+ + "\1\u024e\35\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u024f\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\7\15\1\u0250\36\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u0251\34\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15"+ + "\1\u0252\35\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\10\15\1\u0253\35\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u0254\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u0255\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15"+ + "\1\u0256\22\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u0257\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\3\15\1\u0258\3\15\4\0\46\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u0259\22\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15"+ + "\1\u025a\44\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\20\15\1\u025b\25\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\1\15\1\u025c\44\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u025d\33\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\31\15"+ + "\1\u025e\11\15\1\u025f\2\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\22\15\1\u0260\23\15\23\0\1\15"+ + "\17\0\2\u0261\1\0\4\u0261\4\0\1\u0261\1\0\2\u0261"+ + "\1\0\1\u0261\6\0\2\u0261\12\0\1\u0261\1\0\1\u0261"+ + "\5\0\2\u0261\41\0\1\133\5\0\1\u0262\1\144\2\0"+ + "\2\u0262\1\150\6\0\1\150\75\0\2\15\7\0\7\15"+ + "\4\0\24\15\1\u0263\21\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\26\15\1\u0264\17\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\7\15\1\u0265\36\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15"+ + "\1\u0266\43\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u0267\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u0268\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u0269\34\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\26\15"+ + "\1\u026a\17\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\7\15\1\u026b\36\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\2\15\1\u026c\43\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\7\15\1\u026d\36\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15"+ + "\1\u026e\34\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\14\15\1\u026f\31\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\24\15\1\u0270\21\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0271\43\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\u0272\31\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\2\15\1\u0273\43\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\u0274\42\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0275\43\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15"+ + "\1\u0276\31\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\12\15\1\u0277\33\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\12\15\1\u0278\33\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\7\15\1\u0279\36\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15"+ + "\1\u027a\34\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\16\15\1\u027b\27\15\23\0\1\15\17\0\2\u027c"+ + "\1\0\4\u027c\4\0\1\u027c\1\0\2\u027c\1\0\1\u027c"+ + "\6\0\2\u027c\12\0\1\u027c\1\0\1\u027c\5\0\2\u027c"+ + "\41\0\1\133\5\0\1\u027d\1\144\2\0\2\u027d\1\150"+ + "\6\0\1\150\75\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\u027e\33\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\13\15\1\u027f\32\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\11\15\1\u0280\34\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\20\15\1\u0281\25\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\20\15"+ + "\1\u0282\25\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\15\15\1\u0283\30\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\3\15\1\u0284\42\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\6\15\1\u0285\37\15"+ + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15"+ + "\1\u0286\33\15\23\0\1\15\6\0\2\15\7\0\7\15"+ + "\4\0\37\15\1\u0287\6\15\23\0\1\15\6\0\2\15"+ + "\7\0\7\15\4\0\44\15\1\u0288\1\15\23\0\1\15"+ + "\6\0\2\15\7\0\7\15\4\0\1\u0289\45\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u028a"+ + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\10\15\1\u028b\35\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\10\15\1\u028c\35\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\7\15\1\u028d\36\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u028e"+ + "\42\15\23\0\1\15\11\0\1\133\5\0\1\u028f\1\144"+ + "\2\0\2\u028f\1\150\6\0\1\150\75\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0290\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\10\15\1\u0291\35\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\35\15\1\u0292"+ + "\10\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\14\15\1\u0293\31\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u0294\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\7\15\1\u0295\36\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u0296"+ + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\16\15\1\u0297\27\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\23\15\1\u0298\22\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\26\15\1\u0299\17\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\21\15\1\u029a"+ + "\24\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\22\15\1\u029b\23\15\23\0\1\15\11\0\1\133\5\0"+ + "\1\u029c\1\144\2\0\2\u029c\1\150\6\0\1\150\75\0"+ + "\2\15\7\0\7\15\4\0\40\15\1\u029d\5\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u029e"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\13\15\1\u029f\32\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u02a0\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\44\15\1\u02a1\1\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\24\15\1\u02a2"+ + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\23\15\1\u02a3\22\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\2\15\1\u02a4\43\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u02a5\42\15\23\0"+ + "\1\15\11\0\1\133\5\0\1\u02a6\1\144\2\0\2\u02a6"+ + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0"+ + "\16\15\1\u02a7\27\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\6\15\1\u02a8\37\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\3\15\1\u02a9\42\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u02aa"+ + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\13\15\1\u02ab\32\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u02ac\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\6\15\1\u02ad\37\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\21\15\1\u02ae"+ + "\24\15\23\0\1\15\11\0\1\133\5\0\1\u02af\1\144"+ + "\2\0\2\u02af\1\150\6\0\1\150\75\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u02b0\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\16\15\1\u02b1\27\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\23\15\1\u02b2"+ + "\22\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\2\15\1\u02b3\43\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\44\15\1\u02b4\1\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\44\15\1\u02b5\1\15\23\0"+ + "\1\15\11\0\1\133\5\0\1\u02b6\1\144\2\0\2\u02b6"+ + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0"+ + "\21\15\1\u02b7\24\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\12\15\1\u02b8\33\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\40\15\1\u02b9\5\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u02ba"+ + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\13\15\1\u02bb\32\15\23\0\1\15\11\0\1\133\5\0"+ + "\1\u02bc\1\144\2\0\2\u02bc\1\150\6\0\1\150\75\0"+ + "\2\15\7\0\7\15\4\0\11\15\1\u02bd\34\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u02be"+ + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\23\15\1\u02bf\22\15\23\0\1\15\6\0\2\15\7\0"+ + "\7\15\4\0\23\15\1\u02c0\22\15\23\0\1\15\6\0"+ + "\2\15\7\0\7\15\4\0\22\15\1\u02c1\23\15\23\0"+ + "\1\15\6\0\2\15\7\0\7\15\4\0\12\15\1\u02c2"+ + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0"+ + "\21\15\1\u02c3\24\15\23\0\1\15"; - private static int[] zzUnpackRowMap() { - int[] result = new int[705]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; + private static int [] zzUnpackTrans() { + int [] result = new int[46116]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); } + return j; + } - private static int zzUnpackRowMap(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); - } - return j; + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\6\0\1\11\1\1\1\11\11\1\1\11\3\1\1\11"+ + "\27\1\10\11\1\1\2\11\5\1\1\11\2\1\2\11"+ + "\4\1\1\11\2\1\1\11\1\1\1\11\1\1\1\11"+ + "\3\1\1\11\1\1\1\0\3\11\2\0\1\1\1\0"+ + "\1\1\2\11\1\1\1\11\3\1\1\0\2\1\1\0"+ + "\2\11\1\0\75\1\12\11\1\1\6\11\1\1\1\11"+ + "\1\1\6\0\2\11\3\1\1\11\2\0\1\11\3\0"+ + "\1\11\1\0\1\11\1\1\2\11\4\1\1\0\113\1"+ + "\1\11\12\0\1\11\5\0\1\11\111\1\1\11\1\0"+ + "\1\11\1\1\1\0\1\11\12\0\100\1\10\0\67\1"+ + "\2\0\153\1\1\11\107\1"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[707]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); } + return j; + } - /** - * The transition table of the DFA - */ - private static final int[] ZZ_TRANS = zzUnpackTrans(); + /** the input device */ + private java.io.Reader zzReader; - private static final String ZZ_TRANS_PACKED_0 - = "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\7" - + "\1\16\1\17\1\20\1\21\1\12\1\22\1\23\1\24" - + "\1\25\2\15\2\25\1\15\1\26\1\7\1\27\1\30" - + "\1\31\1\32\1\33\1\34\1\15\1\35\1\36\1\37" - + "\1\40\1\41\1\42\1\43\1\44\1\45\1\46\1\47" - + "\1\15\1\50\1\15\1\51\1\52\1\15\1\53\2\15" - + "\1\54\12\15\1\55\1\56\1\57\1\60\1\61\1\62" - + "\1\63\1\64\1\65\1\66\1\67\1\70\1\71\1\72" - + "\1\73\1\74\1\75\1\76\1\77\1\7\1\12\1\7" - + "\1\100\1\101\1\102\13\100\1\103\10\100\1\104\74\100" - + "\1\105\1\101\1\102\24\105\1\106\1\103\73\105\1\7" - + "\1\107\1\110\1\111\2\7\1\112\4\7\1\113\1\114" - + "\4\7\2\112\2\7\1\112\4\7\46\112\22\7\1\111" - + "\1\7\1\115\1\116\1\117\7\115\1\120\111\115\1\121" - + "\1\101\1\102\24\121\1\122\1\121\1\123\72\121\126\0" - + "\1\11\124\0\1\12\10\0\1\12\105\0\1\12\5\0" - + "\1\124\1\125\7\0\1\126\123\0\1\127\114\0\2\15" - + "\7\0\7\15\4\0\46\15\23\0\1\15\10\0\1\130" - + "\124\0\1\131\1\132\4\0\2\133\2\0\2\133\105\0" - + "\1\134\3\0\1\135\1\136\1\0\1\137\3\0\2\134" - + "\2\0\1\134\4\0\46\134\37\0\1\140\1\0\1\141" - + "\123\0\1\142\117\0\1\133\5\0\1\143\1\144\1\145" - + "\1\0\1\146\1\147\1\150\6\0\1\150\22\0\1\145" - + "\55\0\1\133\5\0\2\25\2\0\2\25\1\150\6\0" - + "\1\150\104\0\1\151\10\0\1\152\103\0\2\15\7\0" - + "\7\15\4\0\1\15\1\153\44\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\154\1\155\42\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\3\15" - + "\1\156\12\15\1\157\5\15\1\160\1\161\20\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\162" - + "\1\15\1\163\35\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\164\3\15\1\165\6\15\1\166" - + "\1\15\1\167\25\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\170\6\15\1\171\1\15\1\172" - + "\3\15\1\173\26\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\15\1\174\22\15\1\175\21\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\176" - + "\1\177\7\15\1\200\32\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\1\15\1\201\1\202\1\203\3\15" - + "\1\204\10\15\1\205\1\15\1\206\23\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\6\15\1\207\1\15" - + "\1\210\4\15\1\211\5\15\1\212\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\6\15\1\213\1\15" - + "\1\214\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\215\4\15\1\216\3\15\1\217\6\15" - + "\1\220\23\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\221\2\15\1\222\1\223\2\15\1\224" - + "\1\225\32\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\226\4\15\1\227\36\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\12\15\1\230\5\15" - + "\1\231\25\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\232\1\15\1\233\7\15\1\234\2\15" - + "\1\235\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\236\45\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\237\3\15\1\240\36\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\241" - + "\4\15\1\242\36\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\243\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\244\7\15\1\245" - + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\10\15\1\246\35\15\23\0\1\15\15\0\1\247\123\0" - + "\1\250\75\0\1\251\25\0\1\252\76\0\1\253\24\0" - + "\1\254\77\0\1\255\23\0\1\256\123\0\1\257\106\0" - + "\1\100\2\0\13\100\1\0\10\100\1\0\74\100\2\0" - + "\1\102\121\0\1\260\2\0\13\260\1\261\1\262\3\260" - + "\2\262\2\260\1\263\1\264\1\260\1\265\1\266\6\260" - + "\1\267\1\270\1\260\1\271\1\260\1\272\7\260\1\273" - + "\41\260\3\0\1\105\2\0\24\105\2\0\73\105\1\260" - + "\2\0\13\260\1\261\10\260\1\263\1\264\1\260\1\265" - + "\1\266\6\260\1\267\1\270\1\260\1\271\1\260\1\272" - + "\7\260\1\273\41\260\5\0\1\110\124\0\1\111\10\0" - + "\1\111\105\0\1\111\7\0\2\274\1\275\3\0\1\276" - + "\1\277\1\0\7\274\4\0\46\274\23\0\1\274\3\0" - + "\1\111\2\0\1\274\5\0\1\114\4\0\2\274\2\0" - + "\1\274\4\0\46\274\22\0\1\111\3\0\1\117\125\0" - + "\1\300\1\0\1\301\12\0\2\301\2\0\1\301\4\0" - + "\46\301\24\0\1\121\2\0\24\121\1\0\1\121\1\0" - + "\72\121\1\302\2\0\24\302\1\263\1\302\1\303\1\265" - + "\1\266\6\302\1\267\1\270\1\302\1\304\1\302\1\272" - + "\7\302\1\305\41\302\3\0\1\124\1\306\1\307\121\124" - + "\5\310\1\311\116\310\11\0\1\312\120\0\1\313\12\0" - + "\2\313\2\0\1\313\4\0\46\313\43\0\2\133\2\0" - + "\2\133\1\150\6\0\1\150\75\0\1\314\1\134\1\315" - + "\2\0\1\316\1\317\2\0\2\134\2\314\2\134\1\314" - + "\4\0\46\314\23\0\1\134\15\0\1\320\121\0\1\321" - + "\1\0\1\322\123\0\1\323\117\0\1\133\5\0\1\143" - + "\1\144\2\0\1\146\1\147\1\150\6\0\1\150\100\0" - + "\1\133\5\0\2\144\2\0\2\144\1\150\6\0\1\150" - + "\106\0\1\324\1\325\1\0\4\325\4\0\1\325\1\0" - + "\2\325\1\0\1\325\6\0\2\325\12\0\1\325\1\0" - + "\1\325\5\0\2\325\41\0\1\133\5\0\1\147\1\144" - + "\2\0\2\147\1\150\6\0\1\150\100\0\1\133\5\0" - + "\1\326\1\144\2\0\2\326\1\150\6\0\1\150\106\0" - + "\2\327\2\0\2\327\1\0\1\330\66\0\1\330\14\0" - + "\2\15\7\0\7\15\4\0\2\15\1\331\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\332" - + "\11\15\1\333\22\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\10\15\1\334\35\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\5\15\1\335\40\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\336" - + "\37\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\3\15\1\337\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\340\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\341\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\342" - + "\2\15\1\343\4\15\1\344\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\10\15\1\345\35\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\346" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\15\1\347\44\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\350\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\351\3\15\1\352" - + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\353\20\15\1\354\24\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\355\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\356\31\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\357\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\17\15\1\360\5\15\1\361\20\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\23\15\1\362\22\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\363\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\364\7\15\1\365\6\15\1\366\23\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\367\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\370\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\26\15\1\371\17\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\1\15\1\372\10\15" - + "\1\373\33\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\21\15\1\374\24\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\6\15\1\375\2\15\1\376\34\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\32\15" - + "\1\377\13\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\21\15\1\u0100\24\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\2\15\1\u0101\43\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u0102\1\15" - + "\1\u0103\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\15\15\1\u0104\1\u0105\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\21\15\1\u0106\24\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u0107" - + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u0108\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\5\15\1\u0109\40\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u010a\44\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u010b" - + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\10\15\1\u010c\35\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\10\15\1\u010d\35\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u010e\42\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u010f" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u0110\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u0111\4\15\1\u0112\2\15\1\u0113" - + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\5\15\1\u0114\40\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\u0115\45\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\3\15\1\u0116\42\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u0117\1\u0118" - + "\1\u0119\6\15\1\u011a\27\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\1\15\1\u011b\44\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u011c\33\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15" - + "\1\u011d\34\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\11\15\1\u011e\34\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\1\15\1\u011f\44\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\44\15\1\u0120\1\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15" - + "\1\u0121\22\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\15\15\1\u0122\30\15\23\0\1\15\15\0\1\u0123" - + "\125\0\1\u0124\3\0\2\u0124\116\0\2\u0125\1\0\4\u0125" - + "\4\0\1\u0125\1\0\2\u0125\1\0\1\u0125\6\0\2\u0125" - + "\12\0\1\u0125\1\0\1\u0125\5\0\2\u0125\47\0\2\u0126" - + "\1\0\4\u0126\4\0\1\u0126\1\0\2\u0126\1\0\1\u0126" - + "\6\0\2\u0126\12\0\1\u0126\1\0\1\u0126\5\0\2\u0126" - + "\36\0\1\u0127\12\0\2\u0127\2\0\1\u0127\4\0\46\u0127" - + "\40\0\1\276\1\277\122\0\1\277\1\0\1\u0128\113\0" - + "\1\u0129\12\0\2\u0129\2\0\1\u0129\4\0\46\u0129\32\0" - + "\1\u012a\1\301\1\u012b\2\0\1\115\1\u012c\2\0\2\301" - + "\2\u012a\2\301\1\u012a\4\0\46\u012a\23\0\1\301\2\0" - + "\1\307\121\0\5\310\1\u012d\116\310\4\0\1\307\1\311" - + "\124\0\2\313\3\0\1\u012e\3\0\7\313\4\0\46\313" - + "\23\0\1\313\6\0\2\314\1\u012f\2\0\1\316\1\u0130" - + "\1\u0131\1\0\7\314\4\0\46\314\23\0\1\314\6\0" - + "\1\u0132\12\0\2\u0132\2\0\1\u0132\4\0\46\u0132\32\0" - + "\1\u0133\5\0\1\317\4\0\2\u0133\2\0\1\u0133\4\0" - + "\46\u0133\41\0\1\u0134\125\0\2\u0135\1\0\4\u0135\4\0" - + "\1\u0135\1\0\2\u0135\1\0\1\u0135\6\0\2\u0135\12\0" - + "\1\u0135\1\0\1\u0135\5\0\2\u0135\41\0\1\133\5\0" - + "\1\u0136\1\144\2\0\2\u0136\1\150\6\0\1\150\106\0" - + "\2\327\2\0\2\327\105\0\2\15\7\0\7\15\4\0" - + "\3\15\1\u0137\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\13\15\1\u0138\32\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\7\15\1\u0139\36\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u013a" - + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\20\15\1\u013b\25\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u013c\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\16\15\1\u013d\27\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u013e" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u013f\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\5\15\1\u0140\40\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\16\15\1\u0141\27\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\u0142" - + "\2\15\1\u0143\34\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0144\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u0145\7\15\1\u0146" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\21\15\1\u0147\24\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0148\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u0149\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u014a" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\15\1\u014b\44\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\16\15\1\u014c\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u014d\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u014e" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u014f\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\5\15\1\u0150\40\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u0151\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u0152" - + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\26\15\1\u0153\17\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\26\15\1\u0154\17\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\7\15\1\u0155\36\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\6\15\1\u0156" - + "\37\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0157\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u0158\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u0159\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u015a" - + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\7\15\1\u015b\6\15\1\u015c\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u015d\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u015e" - + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\3\15\1\u015f\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u0160\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\16\15\1\u0161\27\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0162" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\6\15\1\u0163\37\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\7\15\1\u0164\36\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u0165\42\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\5\15\1\u0166" - + "\40\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\26\15\1\u0167\17\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\14\15\1\u0168\31\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\20\15\1\u0169\25\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u016a" - + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\24\15\1\u016b\21\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u016c\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\10\15\1\u016d\13\15\1\u016e" - + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\4\15\1\u016f\41\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\16\15\1\u0170\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\22\15\1\u0171\23\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\20\15\1\u0172" - + "\25\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\13\15\1\u0173\32\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\15\1\u0174\44\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u0175\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u0176" - + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\27\15\1\u0177\3\15\1\u0178\6\15\1\u0179\3\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\7\15\1\u017a" - + "\36\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u017b\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\u017c\45\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u017d\33\15\23\0\1\15" - + "\17\0\1\u017e\3\0\2\u017e\116\0\2\u017f\1\0\4\u017f" - + "\4\0\1\u017f\1\0\2\u017f\1\0\1\u017f\6\0\2\u017f" - + "\12\0\1\u017f\1\0\1\u017f\5\0\2\u017f\47\0\2\u0180" - + "\1\0\4\u0180\4\0\1\u0180\1\0\2\u0180\1\0\1\u0180" - + "\6\0\2\u0180\12\0\1\u0180\1\0\1\u0180\5\0\2\u0180" - + "\36\0\2\u0127\4\0\1\276\1\277\1\0\7\u0127\4\0" - + "\46\u0127\23\0\1\u0127\1\u0128\2\0\13\u0128\1\u0181\105\u0128" - + "\6\0\2\u0129\1\u0182\2\0\1\u0183\3\0\7\u0129\4\0" - + "\46\u0129\23\0\1\u0129\6\0\2\u012a\1\u0184\2\0\1\115" - + "\1\u0185\1\u0186\1\0\7\u012a\4\0\46\u012a\23\0\1\u012a" - + "\6\0\1\u0187\12\0\2\u0187\2\0\1\u0187\4\0\46\u0187" - + "\32\0\1\u0188\5\0\1\u012c\4\0\2\u0188\2\0\1\u0188" - + "\4\0\46\u0188\24\0\4\310\1\307\1\u012d\116\310\6\0" - + "\1\u0189\12\0\2\u0189\2\0\1\u0189\4\0\46\u0189\32\0" - + "\1\u0133\5\0\1\u0130\1\u0131\3\0\2\u0133\2\0\1\u0133" - + "\4\0\46\u0133\40\0\1\u0131\1\0\1\u018a\113\0\1\u018b" - + "\1\u0132\3\0\1\316\1\317\2\0\2\u0132\2\u018b\2\u0132" - + "\1\u018b\4\0\46\u018b\23\0\1\u0132\6\0\2\u0133\1\u018c" - + "\3\0\1\u018d\1\u0131\1\0\7\u0133\4\0\46\u0133\23\0" - + "\1\u0133\17\0\2\u018e\1\0\4\u018e\4\0\1\u018e\1\0" - + "\2\u018e\1\0\1\u018e\6\0\2\u018e\12\0\1\u018e\1\0" - + "\1\u018e\5\0\2\u018e\41\0\1\133\5\0\1\u018f\1\144" - + "\2\0\2\u018f\1\150\6\0\1\150\75\0\2\15\7\0" - + "\7\15\4\0\4\15\1\u0190\41\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u0191\44\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\24\15\1\u0192" - + "\21\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\7\15\1\u0193\36\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\10\15\1\u0194\35\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\20\15\1\u0195\25\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u0196" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u0197\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0198\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u0199\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\12\15\1\u019a" - + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\30\15\1\u019b\10\15\1\u019c\4\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u019d\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u019e" - + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\5\15\1\u019f\40\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\15\1\u01a0\44\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\12\15\1\u01a1\33\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\32\15\1\u01a2" - + "\13\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\6\15\1\u01a3\37\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u01a4\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\33\15\1\u01a5\12\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u01a6" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u01a7\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\17\15\1\u01a8\26\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\7\15\1\u01a9\36\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u01aa" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\15\1\u01ab\44\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u01ac\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u01ad\44\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u01ae" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\15\15\1\u01af\30\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u01b0\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\13\15\1\u01b1\32\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u01b2" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u01b3\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\23\15\1\u01b4\22\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\2\15\1\u01b5\43\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\23\15\1\u01b6" - + "\22\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u01b7\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u01b8\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u01b9\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\37\15\1\u01ba" - + "\2\15\1\u01bb\3\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u01bc\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\32\15\1\u01bd\13\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u01be" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\11\15\1\u01bf\34\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u01c0\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u01c1\42\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\12\15\1\u01c2" - + "\33\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\1\15\1\u01c3\44\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\1\u01c4\45\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\14\15\1\u01c5\31\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u01c6\35\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15" - + "\1\u01c7\44\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u01c8\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\2\15\1\u01c9\43\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\30\15\1\u01ca\15\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01cb\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u01cc\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\10\15\1\u01cd\35\15\23\0\1\15" - + "\1\u0128\2\0\11\u0128\1\u0181\1\u0128\1\u0181\105\u0128\6\0" - + "\1\u01ce\12\0\2\u01ce\2\0\1\u01ce\4\0\46\u01ce\32\0" - + "\1\u01cf\12\0\2\u01cf\2\0\1\u01cf\4\0\46\u01cf\32\0" - + "\1\u0188\5\0\1\u0185\1\u0186\3\0\2\u0188\2\0\1\u0188" - + "\4\0\46\u0188\40\0\1\u0186\1\0\1\u01d0\113\0\1\u01d1" - + "\1\u0187\3\0\1\115\1\u012c\2\0\2\u0187\2\u01d1\2\u0187" - + "\1\u01d1\4\0\46\u01d1\23\0\1\u0187\6\0\2\u0188\1\u01d2" - + "\3\0\1\u01d3\1\u0186\1\0\7\u0188\4\0\46\u0188\23\0" - + "\1\u0188\6\0\1\u018b\1\u0189\3\0\1\316\1\u0130\1\u0131" - + "\1\0\2\u0189\2\u018b\2\u0189\1\u018b\4\0\46\u018b\23\0" - + "\1\u0189\1\u018a\2\0\13\u018a\1\u01d4\105\u018a\6\0\2\u018b" - + "\1\u018c\2\0\1\316\1\u0130\1\u0131\1\0\7\u018b\4\0" - + "\46\u018b\23\0\1\u018b\6\0\1\u01d5\12\0\2\u01d5\2\0" - + "\1\u01d5\4\0\46\u01d5\40\0\1\u018d\1\u0131\125\0\2\u01d6" - + "\1\0\4\u01d6\4\0\1\u01d6\1\0\2\u01d6\1\0\1\u01d6" - + "\6\0\2\u01d6\12\0\1\u01d6\1\0\1\u01d6\5\0\2\u01d6" - + "\41\0\1\133\5\0\1\u01d7\1\144\2\0\2\u01d7\1\150" - + "\6\0\1\150\75\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01d8\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u01d9\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\23\15\1\u01da\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u01db\31\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01dc\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\41\15\1\u01dd\4\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\5\15\1\u01de\40\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\16\15\1\u01df\27\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15" - + "\1\u01e0\44\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\u01e1\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\20\15\1\u01e2\25\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u01e3\33\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01e4\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\u01e5\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\21\15\1\u01e6\24\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\3\15\1\u01e7\42\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\11\15" - + "\1\u01e8\34\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u01e9\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\15\15\1\u01ea\30\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u01eb\35\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u01ec\4\15\1\u01ed\30\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\23\15\1\u01ee\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u01ef\34\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\23\15" - + "\1\u01f0\22\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u01f1\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\14\15\1\u01f2\31\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\16\15\1\u01f3\27\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u01f4\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\5\15\1\u01f5\40\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u01f6\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u01f7\22\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\u01f8\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u01f9\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\20\15\1\u01fa\25\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\7\15\1\u01fb\36\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\3\15" - + "\1\u01fc\42\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\u01fd\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\5\15\1\u01fe\40\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\30\15\1\u01ff\13\15" - + "\1\u0200\1\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\11\15\1\u0201\34\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\26\15\1\u0202\17\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u0203\40\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\6\15" - + "\1\u0204\37\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\26\15\1\u0205\17\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\16\15\1\u0206\27\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u0207\22\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\1\15" - + "\1\u0208\44\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\10\15\1\u0209\35\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\26\15\1\u020a\17\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\1\15\1\u020b\44\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15" - + "\1\u020c\33\15\23\0\1\15\6\0\2\u01ce\3\0\1\u0183" - + "\3\0\7\u01ce\4\0\46\u01ce\23\0\1\u01ce\6\0\1\u01d1" - + "\1\u01cf\3\0\1\115\1\u0185\1\u0186\1\0\2\u01cf\2\u01d1" - + "\2\u01cf\1\u01d1\4\0\46\u01d1\23\0\1\u01cf\1\u01d0\2\0" - + "\13\u01d0\1\u020d\105\u01d0\6\0\2\u01d1\1\u01d2\2\0\1\115" - + "\1\u0185\1\u0186\1\0\7\u01d1\4\0\46\u01d1\23\0\1\u01d1" - + "\6\0\1\u020e\12\0\2\u020e\2\0\1\u020e\4\0\46\u020e" - + "\40\0\1\u01d3\1\u0186\106\0\1\u018a\2\0\10\u018a\1\u020f" - + "\1\u01d4\1\u018a\1\u01d4\105\u018a\6\0\2\u01d5\4\0\1\u018d" - + "\1\u0131\1\0\7\u01d5\4\0\46\u01d5\23\0\1\u01d5\17\0" - + "\2\u0210\1\0\4\u0210\4\0\1\u0210\1\0\2\u0210\1\0" - + "\1\u0210\6\0\2\u0210\12\0\1\u0210\1\0\1\u0210\5\0" - + "\2\u0210\41\0\1\133\5\0\1\u0211\1\144\2\0\2\u0211" - + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0" - + "\37\15\1\u0212\6\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0213\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\13\15\1\u0214\32\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u0215" - + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\16\15\1\u0216\27\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u0217\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\u0218\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u0219" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\3\15\1\u021a\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u021b\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\1\15\1\u021c\44\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\43\15\1\u021d" - + "\2\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\34\15\1\u021e\11\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\5\15\1\u021f\40\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u0220\42\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0221" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0222\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u0223\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\10\15\1\u0224\35\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\37\15\1\u0225" - + "\6\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\11\15\1\u0226\34\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u0227\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\5\15\1\u0228\40\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\3\15\1\u0229" - + "\42\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\22\15\1\u022a\23\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\7\15\1\u022b\36\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\24\15\1\u022c\21\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\1\15\1\u022d" - + "\44\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\3\15\1\u022e\42\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u022f\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\6\15\1\u0230\37\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u0231" - + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0232\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\2\15\1\u0233\43\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u0234\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u0235" - + "\34\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0236\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u0237\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\u0238\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\11\15\1\u0239" - + "\34\15\23\0\1\15\1\u01d0\2\0\10\u01d0\1\u023a\1\u020d" - + "\1\u01d0\1\u020d\105\u01d0\6\0\2\u020e\4\0\1\u01d3\1\u0186" - + "\1\0\7\u020e\4\0\46\u020e\23\0\1\u020e\17\0\2\u023b" - + "\1\0\4\u023b\4\0\1\u023b\1\0\2\u023b\1\0\1\u023b" - + "\6\0\2\u023b\12\0\1\u023b\1\0\1\u023b\5\0\2\u023b" - + "\41\0\1\133\5\0\1\u023c\1\144\2\0\2\u023c\1\150" - + "\6\0\1\150\75\0\2\15\7\0\7\15\4\0\7\15" - + "\1\u023d\36\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u023e\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\3\15\1\u023f\42\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\31\15\1\u0240\14\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\26\15" - + "\1\u0241\17\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u0242\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\23\15\1\u0243\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\5\15\1\u0244\40\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\26\15" - + "\1\u0245\17\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\u0246\42\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u0247\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0248\43\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\u0249\27\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\5\15\1\u024a\40\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\36\15\1\u024b\7\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u024c\35\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u024d\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\7\15\1\u024e\36\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\11\15\1\u024f\34\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\10\15\1\u0250\35\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\10\15" - + "\1\u0251\35\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u0252\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u0253\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\23\15\1\u0254\22\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u0255\43\15\23\0\1\15\6\0\2\15\7\0\3\15" - + "\1\u0256\3\15\4\0\46\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\23\15\1\u0257\22\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\1\15\1\u0258\44\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\20\15" - + "\1\u0259\25\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\1\15\1\u025a\44\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\12\15\1\u025b\33\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\31\15\1\u025c\11\15" - + "\1\u025d\2\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\22\15\1\u025e\23\15\23\0\1\15\17\0\2\u025f" - + "\1\0\4\u025f\4\0\1\u025f\1\0\2\u025f\1\0\1\u025f" - + "\6\0\2\u025f\12\0\1\u025f\1\0\1\u025f\5\0\2\u025f" - + "\41\0\1\133\5\0\1\u0260\1\144\2\0\2\u0260\1\150" - + "\6\0\1\150\75\0\2\15\7\0\7\15\4\0\24\15" - + "\1\u0261\21\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\26\15\1\u0262\17\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\7\15\1\u0263\36\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\2\15\1\u0264\43\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u0265\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u0266\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\11\15\1\u0267\34\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\26\15\1\u0268\17\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\7\15" - + "\1\u0269\36\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\2\15\1\u026a\43\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\7\15\1\u026b\36\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u026c\34\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\14\15" - + "\1\u026d\31\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\24\15\1\u026e\21\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\2\15\1\u026f\43\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u0270\31\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\2\15" - + "\1\u0271\43\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\u0272\42\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\2\15\1\u0273\43\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\14\15\1\u0274\31\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\12\15" - + "\1\u0275\33\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\12\15\1\u0276\33\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\7\15\1\u0277\36\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\11\15\1\u0278\34\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\16\15" - + "\1\u0279\27\15\23\0\1\15\17\0\2\u027a\1\0\4\u027a" - + "\4\0\1\u027a\1\0\2\u027a\1\0\1\u027a\6\0\2\u027a" - + "\12\0\1\u027a\1\0\1\u027a\5\0\2\u027a\41\0\1\133" - + "\5\0\1\u027b\1\144\2\0\2\u027b\1\150\6\0\1\150" - + "\75\0\2\15\7\0\7\15\4\0\12\15\1\u027c\33\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\13\15" - + "\1\u027d\32\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\11\15\1\u027e\34\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\20\15\1\u027f\25\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\20\15\1\u0280\25\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\15\15" - + "\1\u0281\30\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\3\15\1\u0282\42\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\6\15\1\u0283\37\15\23\0\1\15" - + "\6\0\2\15\7\0\7\15\4\0\12\15\1\u0284\33\15" - + "\23\0\1\15\6\0\2\15\7\0\7\15\4\0\37\15" - + "\1\u0285\6\15\23\0\1\15\6\0\2\15\7\0\7\15" - + "\4\0\44\15\1\u0286\1\15\23\0\1\15\6\0\2\15" - + "\7\0\7\15\4\0\1\u0287\45\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\11\15\1\u0288\34\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\10\15\1\u0289" - + "\35\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\10\15\1\u028a\35\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\7\15\1\u028b\36\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\3\15\1\u028c\42\15\23\0" - + "\1\15\11\0\1\133\5\0\1\u028d\1\144\2\0\2\u028d" - + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u028e\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\10\15\1\u028f\35\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\35\15\1\u0290\10\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\14\15\1\u0291" - + "\31\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u0292\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\7\15\1\u0293\36\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\13\15\1\u0294\32\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\16\15\1\u0295" - + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\23\15\1\u0296\22\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\26\15\1\u0297\17\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\21\15\1\u0298\24\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\22\15\1\u0299" - + "\23\15\23\0\1\15\11\0\1\133\5\0\1\u029a\1\144" - + "\2\0\2\u029a\1\150\6\0\1\150\75\0\2\15\7\0" - + "\7\15\4\0\40\15\1\u029b\5\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\u029c\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u029d" - + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u029e\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\44\15\1\u029f\1\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\24\15\1\u02a0\21\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\23\15\1\u02a1" - + "\22\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\2\15\1\u02a2\43\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u02a3\42\15\23\0\1\15\11\0" - + "\1\133\5\0\1\u02a4\1\144\2\0\2\u02a4\1\150\6\0" - + "\1\150\75\0\2\15\7\0\7\15\4\0\16\15\1\u02a5" - + "\27\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\6\15\1\u02a6\37\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\3\15\1\u02a7\42\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\14\15\1\u02a8\31\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u02a9" - + "\32\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u02aa\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\6\15\1\u02ab\37\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\21\15\1\u02ac\24\15\23\0" - + "\1\15\11\0\1\133\5\0\1\u02ad\1\144\2\0\2\u02ad" - + "\1\150\6\0\1\150\75\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u02ae\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\16\15\1\u02af\27\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\23\15\1\u02b0\22\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\2\15\1\u02b1" - + "\43\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\44\15\1\u02b2\1\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\44\15\1\u02b3\1\15\23\0\1\15\11\0" - + "\1\133\5\0\1\u02b4\1\144\2\0\2\u02b4\1\150\6\0" - + "\1\150\75\0\2\15\7\0\7\15\4\0\21\15\1\u02b5" - + "\24\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\12\15\1\u02b6\33\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\40\15\1\u02b7\5\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\13\15\1\u02b8\32\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\13\15\1\u02b9" - + "\32\15\23\0\1\15\11\0\1\133\5\0\1\u02ba\1\144" - + "\2\0\2\u02ba\1\150\6\0\1\150\75\0\2\15\7\0" - + "\7\15\4\0\11\15\1\u02bb\34\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\16\15\1\u02bc\27\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\23\15\1\u02bd" - + "\22\15\23\0\1\15\6\0\2\15\7\0\7\15\4\0" - + "\23\15\1\u02be\22\15\23\0\1\15\6\0\2\15\7\0" - + "\7\15\4\0\22\15\1\u02bf\23\15\23\0\1\15\6\0" - + "\2\15\7\0\7\15\4\0\12\15\1\u02c0\33\15\23\0" - + "\1\15\6\0\2\15\7\0\7\15\4\0\21\15\1\u02c1" - + "\24\15\23\0\1\15"; + /** the current state of the DFA */ + private int zzState; - private static int[] zzUnpackTrans() { - int[] result = new int[45864]; - int offset = 0; - offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); - return result; - } + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; - private static int zzUnpackTrans(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - int j = offset; /* index in unpacked array */ + /** the textposition at the last accepting state */ + private int zzMarkedPos; - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - value--; - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } + /** the current text position in the buffer */ + private int zzCurrentPos; + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; - private static final int ZZ_NO_MATCH = 1; + /** number of newlines encountered up to the start of the matched text */ + private int yyline; - private static final int ZZ_PUSHBACK_2BIG = 2; + /** the number of characters up to the start of the matched text */ + private int yychar; - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute(); + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; - private static final String ZZ_ATTRIBUTE_PACKED_0 - = "\6\0\1\11\1\1\1\11\11\1\1\11\3\1\2\11" - + "\26\1\10\11\1\1\2\11\5\1\1\11\2\1\2\11" - + "\4\1\1\11\2\1\1\11\1\1\1\11\1\1\1\11" - + "\3\1\1\11\1\1\1\0\3\11\2\0\1\1\1\0" - + "\1\1\2\11\1\1\1\11\3\1\1\0\2\1\1\0" - + "\2\11\75\1\12\11\1\1\6\11\1\1\1\11\1\1" - + "\6\0\2\11\3\1\1\11\2\0\1\11\3\0\1\11" - + "\1\0\1\11\1\1\2\11\4\1\1\0\112\1\1\11" - + "\12\0\1\11\5\0\1\11\111\1\1\11\1\0\1\11" - + "\1\1\1\0\1\11\12\0\100\1\10\0\67\1\2\0" - + "\153\1\1\11\107\1"; + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; - private static int[] zzUnpackAttribute() { - int[] result = new int[705]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /** + * The number of occupied positions in zzBuffer beyond zzEndRead. + * When a lead/high surrogate has been read from the input stream + * into the final zzBuffer position, this will have a value of 1; + * otherwise, it will have a value of 0. + */ + private int zzFinalHighSurrogate = 0; - private static int zzUnpackAttribute(String packed, int offset, int[] result) { - int i = 0; /* index in packed string */ + /* user code: */ - int j = offset; /* index in unpacked array */ - - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do { - result[j++] = value; - } while (--count > 0); - } - return j; - } - - /** - * the input device - */ - private java.io.Reader zzReader; - - /** - * the current state of the DFA - */ - private int zzState; - - /** - * the current lexical state - */ - private int zzLexicalState = YYINITIAL; - - /** - * this buffer contains the current text to be matched and is the source of - * the yytext() string - */ - private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - - /** - * the textposition at the last accepting state - */ - private int zzMarkedPos; - - /** - * the current text position in the buffer - */ - private int zzCurrentPos; - - /** - * startRead marks the beginning of the yytext() string in the buffer - */ - private int zzStartRead; - - /** - * endRead marks the last character in the buffer, that has been read from - * input - */ - private int zzEndRead; - - /** - * number of newlines encountered up to the start of the matched text - */ - private int yyline; - - /** - * the number of characters up to the start of the matched text - */ - private int yychar; - - /** - * the number of characters from the last newline up to the start of the - * matched text - */ - private int yycolumn; - - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; - - /** - * zzAtEOF == true <=> the scanner is at the EOF - */ - private boolean zzAtEOF; - - /** - * denotes if the user-EOF-code has already been executed - */ - private boolean zzEOFDone; - - /** - * The number of occupied positions in zzBuffer beyond zzEndRead. When a - * lead/high surrogate has been read from the input stream into the final - * zzBuffer position, this will have a value of 1; otherwise, it will have a - * value of 0. - */ - private int zzFinalHighSurrogate = 0; - - /* user code: */ StringBuffer string = new StringBuffer(); private static String xmlTagName = ""; @@ -1280,22 +1234,22 @@ public final class ActionScriptLexer { private final List listeners = new ArrayList<>(); - public void addListener(LexListener listener) { + public void addListener(LexListener listener){ listeners.add(listener); } - public void removeListener(LexListener listener) { + public void removeListener(LexListener listener){ listeners.remove(listener); } - public void informListenersLex(ParsedSymbol s) { - for (LexListener l : listeners) { + public void informListenersLex(ParsedSymbol s){ + for(LexListener l:listeners){ l.onLex(s); } } - public void informListenersPushBack(ParsedSymbol s) { - for (LexListener l : listeners) { + public void informListenersPushBack(ParsedSymbol s){ + for(LexListener l:listeners){ l.onPushBack(s); } } @@ -1307,10 +1261,9 @@ public final class ActionScriptLexer { } ParsedSymbol last; - - public ParsedSymbol lex() throws java.io.IOException, ActionParseException { + public ParsedSymbol lex() throws java.io.IOException, ActionParseException{ ParsedSymbol ret = null; - if (!pushedBack.isEmpty()) { + if (!pushedBack.isEmpty()){ ret = last = pushedBack.pop(); } else { ret = last = yylex(); @@ -1319,1284 +1272,1098 @@ public final class ActionScriptLexer { return ret; } - /** - * Creates a new scanner - * - * @param in the java.io.Reader to read input from. - */ - public ActionScriptLexer(java.io.Reader in) { - this.zzReader = in; + + + /** + * Creates a new scanner + * + * @param in the java.io.Reader to read input from. + */ + public ActionScriptLexer(java.io.Reader in) { + this.zzReader = in; + } + + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x110000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 2916) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; } - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char[] zzUnpackCMap(String packed) { - char[] map = new char[0x110000]; - int i = 0; /* index in packed string */ + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { + /* if not: blow it up */ + char newBuffer[] = new char[zzBuffer.length*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + zzEndRead += zzFinalHighSurrogate; + zzFinalHighSurrogate = 0; + } - int j = 0; /* index in unpacked array */ + /* fill the buffer with new input */ + int requested = zzBuffer.length - zzEndRead; + int totalRead = 0; + while (totalRead < requested) { + int numRead = zzReader.read(zzBuffer, zzEndRead + totalRead, requested - totalRead); + if (numRead == -1) { + break; + } + totalRead += numRead; + } - while (i < 2916) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do { - map[j++] = value; - } while (--count > 0); + if (totalRead > 0) { + zzEndRead += totalRead; + if (totalRead == requested) { /* possibly more input available */ + if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { + --zzEndRead; + zzFinalHighSurrogate = 1; } - return map; + } + return false; } - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { + // totalRead = 0: End of stream + return true; + } - /* first: make room (if you can) */ - if (zzStartRead > 0) { - zzEndRead += zzFinalHighSurrogate; - zzFinalHighSurrogate = 0; - System.arraycopy(zzBuffer, zzStartRead, - zzBuffer, 0, - zzEndRead - zzStartRead); + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ - /* translate stored positions */ - zzEndRead -= zzStartRead; - zzCurrentPos -= zzStartRead; - zzMarkedPos -= zzStartRead; - zzStartRead = 0; - } + if (zzReader != null) + zzReader.close(); + } - /* is the buffer big enough? */ - if (zzCurrentPos >= zzBuffer.length - zzFinalHighSurrogate) { - /* if not: blow it up */ - char newBuffer[] = new char[zzBuffer.length * 2]; - System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); - zzBuffer = newBuffer; - zzEndRead += zzFinalHighSurrogate; - zzFinalHighSurrogate = 0; - } - /* fill the buffer with new input */ - int requested = zzBuffer.length - zzEndRead; - int totalRead = 0; - while (totalRead < requested) { - int numRead = zzReader.read(zzBuffer, zzEndRead + totalRead, requested - totalRead); - if (numRead == -1) { - break; - } - totalRead += numRead; - } + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * Internal scan buffer is resized down to its initial length, if it has grown. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + zzFinalHighSurrogate = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + if (zzBuffer.length > ZZ_BUFFERSIZE) + zzBuffer = new char[ZZ_BUFFERSIZE]; + } - if (totalRead > 0) { - zzEndRead += totalRead; - if (totalRead == requested) { /* possibly more input available */ - if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) { - --zzEndRead; - zzFinalHighSurrogate = 1; - } - } - return false; - } + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } - // totalRead = 0: End of stream - return true; + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; } - /** - * Closes the input stream. - * - * @throws java.io.IOException - */ - public final void yyclose() throws java.io.IOException { - zzAtEOF = true; /* indicate end of file */ + throw new Error(message); + } - zzEndRead = zzStartRead; /* invalidate buffer */ - if (zzReader != null) { - zzReader.close(); - } - } + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); - /** - * Resets the scanner to read from a new input stream. Does not close the - * old reader. - * - * All internal variables are reset, the old input stream - * cannot be reused (internal buffer is discarded and lost). Lexical - * state is set to ZZ_INITIAL. - * - * Internal scan buffer is resized down to its initial length, if it has - * grown. - * - * @param reader the new input stream - */ - public final void yyreset(java.io.Reader reader) { - zzReader = reader; - zzAtBOL = true; - zzAtEOF = false; - zzEOFDone = false; - zzEndRead = zzStartRead = 0; - zzCurrentPos = zzMarkedPos = 0; - zzFinalHighSurrogate = 0; - yyline = yychar = yycolumn = 0; - zzLexicalState = YYINITIAL; - if (zzBuffer.length > ZZ_BUFFERSIZE) { - zzBuffer = new char[ZZ_BUFFERSIZE]; - } - } + zzMarkedPos -= number; + } - /** - * Returns the current lexical state. - * - * @return - */ - public final int yystate() { - return zzLexicalState; - } - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public ParsedSymbol yylex() throws java.io.IOException, ActionParseException { + int zzInput; + int zzAction; - /** - * Returns the text matched by the current regular expression. - * - * @return - */ - public final String yytext() { - return new String(zzBuffer, zzStartRead, zzMarkedPos - zzStartRead); - } + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; - /** - * Returns the character at position pos from the matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. A value from 0 to - * yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer[zzStartRead + pos]; - } + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; - /** - * Returns the length of the matched text region. - * - * @return - */ - public final int yylength() { - return zzMarkedPos - zzStartRead; - } + while (true) { + zzMarkedPosL = zzMarkedPos; - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of yypushback(int) and - * a match-all fallback rule) this method will only be called with things - * that "Can't Possibly Happen". If this method is called, something is - * seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done in error - * fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; - } catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; - } + yychar+= zzMarkedPosL-zzStartRead; - throw new Error(message); - } + zzAction = -1; - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. This number must - * not be greater than yylength()! - */ - public void yypushback(int number) { - if (number > yylength()) { - zzScanError(ZZ_PUSHBACK_2BIG); - } + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; - zzMarkedPos -= number; - } + // set up zzAction for empty match case: + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + } - /** - * Resumes scanning until the next regular expression is matched, the end of - * input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - * @throws com.jpexs.decompiler.flash.action.parser.ActionParseException - */ - public ParsedSymbol yylex() throws java.io.IOException, ActionParseException { - int zzInput; - int zzAction; - - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - char[] zzBufferL = zzBuffer; - char[] zzCMapL = ZZ_CMAP; - - int[] zzTransL = ZZ_TRANS; - int[] zzRowMapL = ZZ_ROWMAP; - int[] zzAttrL = ZZ_ATTRIBUTE; + zzForAction: { while (true) { - zzMarkedPosL = zzMarkedPos; - - yychar += zzMarkedPosL - zzStartRead; - - zzAction = -1; - - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - - zzState = ZZ_LEXSTATE[zzLexicalState]; - - // set up zzAction for empty match case: - int zzAttributes = zzAttrL[zzState]; - if ((zzAttributes & 1) == 1) { - zzAction = zzState; + + if (zzCurrentPosL < zzEndReadL) { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); + } + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; } - - zzForAction: - { - while (true) { - - if (zzCurrentPosL < zzEndReadL) { - zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); - zzCurrentPosL += Character.charCount(zzInput); - } else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } else { - zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); - zzCurrentPosL += Character.charCount(zzInput); - } - } - int zzNext = zzTransL[zzRowMapL[zzState] + zzCMapL[zzInput]]; - if (zzNext == -1) { - break zzForAction; - } - zzState = zzNext; - - zzAttributes = zzAttrL[zzState]; - if ((zzAttributes & 1) == 1) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ((zzAttributes & 8) == 8) { - break zzForAction; - } - } - - } + else { + zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL, zzEndReadL); + zzCurrentPosL += Character.charCount(zzInput); } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; - // store back cached position - zzMarkedPos = zzMarkedPosL; + zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 1: { - } - case 186: - break; - case 2: { - yyline++; - } - case 187: - break; - case 3: { /*ignore*/ - - } - case 188: - break; - case 4: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); - } - case 189: - break; - case 5: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); - } - case 190: - break; - case 6: { - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); - } - case 191: - break; - case 7: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); - } - case 192: - break; - case 8: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); - } - case 193: - break; - case 9: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); - } - case 194: - break; - case 10: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); - } - case 195: - break; - case 11: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); - } - case 196: - break; - case 12: { - string.setLength(0); - yybegin(STRING); - } - case 197: - break; - case 13: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); - } - case 198: - break; - case 14: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); - } - case 199: - break; - case 15: { - string.setLength(0); - yybegin(CHARLITERAL); - } - case 200: - break; - case 16: { - string.setLength(0); - yybegin(OIDENTIFIER); - } - case 201: - break; - case 17: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); - } - case 202: - break; - case 18: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); - } - case 203: - break; - case 19: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); - } - case 204: - break; - case 20: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); - } - case 205: - break; - case 21: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); - } - case 206: - break; - case 22: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); - } - case 207: - break; - case 23: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); - } - case 208: - break; - case 24: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); - } - case 209: - break; - case 25: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); - } - case 210: - break; - case 26: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); - } - case 211: - break; - case 27: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); - } - case 212: - break; - case 28: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); - } - case 213: - break; - case 29: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); - } - case 214: - break; - case 30: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); - } - case 215: - break; - case 31: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); - } - case 216: - break; - case 32: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); - } - case 217: - break; - case 33: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); - } - case 218: - break; - case 34: { - string.append(yytext()); - } - case 219: - break; - case 35: { - yybegin(YYINITIAL); - yyline++; - } - case 220: - break; - case 36: { - yybegin(YYINITIAL); - // length also includes the trailing quote - return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); - } - case 221: - break; - case 37: { - string.append(yytext()); - yyline++; - } - case 222: - break; - case 38: { - yybegin(XML); - string.append(yytext()); - } - case 223: - break; - case 39: { - string.append(yytext()); - yyline++; - } - case 224: - break; - case 40: { - yybegin(YYINITIAL); - // length also includes the trailing quote - return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); - } - case 225: - break; - case 41: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); - } - case 226: - break; - case 42: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); - } - case 227: - break; - case 43: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); - } - case 228: - break; - case 44: { - return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); - } - case 229: - break; - case 45: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); - } - case 230: - break; - case 46: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); - } - case 231: - break; - case 47: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); - } - case 232: - break; - case 48: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); - } - case 233: - break; - case 49: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); - } - case 234: - break; - case 50: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); - } - case 235: - break; - case 51: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); - } - case 236: - break; - case 52: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); - } - case 237: - break; - case 53: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); - } - case 238: - break; - case 54: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); - } - case 239: - break; - case 55: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLOR, yytext()); - } - case 240: - break; - case 56: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); - } - case 241: - break; - case 57: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IN, yytext()); - } - case 242: - break; - case 58: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IF, yytext()); - } - case 243: - break; - case 59: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DO, yytext()); - } - case 244: - break; - case 60: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); - } - case 245: - break; - case 61: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); - } - case 246: - break; - case 62: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); - } - case 247: - break; - case 63: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); - } - case 248: - break; - case 64: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); - } - case 249: - break; - case 65: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); - } - case 250: - break; - case 66: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); - } - case 251: - break; - case 67: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); - } - case 252: - break; - case 68: { - string.append('\\'); /*illegal escape sequence*/ - - } - case 253: - break; - case 69: { - string.append('\"'); - } - case 254: - break; - case 70: { - string.append('\\'); - } - case 255: - break; - case 71: { - string.append('\''); - } - case 256: - break; - case 72: { - string.append('\b'); - } - case 257: - break; - case 73: { - string.append('\r'); - } - case 258: - break; - case 74: { - string.append('\n'); - } - case 259: - break; - case 75: { - string.append('\t'); - } - case 260: - break; - case 76: { - string.append('\f'); - } - case 261: - break; - case 77: { - throw new ActionParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); - } - case 262: - break; - case 78: { - string.append('\u00A7'); - } - case 263: - break; - case 79: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); - } - case 264: - break; - case 80: { - string.setLength(0); - yybegin(XML); - String s = yytext(); - s = s.substring(1, s.length() - 1); - if (s.contains(" ")) { - s = s.substring(0, s.indexOf(' ')); - } - xmlTagName = s; - string.append(yytext()); - } - case 265: - break; - case 81: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); - } - case 266: - break; - case 82: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); - } - case 267: - break; - case 83: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); - } - case 268: - break; - case 84: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); - } - case 269: - break; - case 85: { - return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); - } - case 270: - break; - case 86: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLAND, yytext()); - } - case 271: - break; - case 87: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.CHR, yytext()); - } - case 272: - break; - case 88: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SET, yytext()); - } - case 273: - break; - case 89: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.ORD, yytext()); - } - case 274: - break; - case 90: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); - } - case 275: - break; - case 91: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRY, yytext()); - } - case 276: - break; - case 92: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.INT, yytext()); - } - case 277: - break; - case 93: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.USE, yytext()); - } - case 278: - break; - case 94: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FOR, yytext()); - } - case 279: - break; - case 95: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.VAR, yytext()); - } - case 280: - break; - case 96: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.GET, yytext()); - } - case 281: - break; - case 97: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); - } - case 282: - break; - case 98: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); - } - case 283: - break; - case 99: { - String t = yytext(); - return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, t.substring(2, t.length() - 1)); - } - case 284: - break; - case 100: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); - } - case 285: - break; - case 101: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EACH, yytext()); - } - case 286: - break; - case 102: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.ELSE, yytext()); - } - case 287: - break; - case 103: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.EVAL, yytext()); - } - case 288: - break; - case 104: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CASE, yytext()); - } - case 289: - break; - case 105: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.CALL, yytext()); - } - case 290: - break; - case 106: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOP, yytext()); - } - case 291: - break; - case 107: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); - } - case 292: - break; - case 108: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); - } - case 293: - break; - case 109: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); - } - case 294: - break; - case 110: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WITH, yytext()); - } - case 295: - break; - case 111: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PLAY, yytext()); - } - case 296: - break; - case 112: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); - } - case 297: - break; - case 113: { - char val = (char) Integer.parseInt(yytext().substring(1), 8); - string.append(val); - } - case 298: - break; - case 114: { - char val = (char) Integer.parseInt(yytext().substring(2), 16); - string.append(val); - } - case 299: - break; - case 115: { - string.append(yytext()); - String endtagname = yytext(); - endtagname = endtagname.substring(2, endtagname.length() - 1); - if (endtagname.equals(xmlTagName)) { - yybegin(YYINITIAL); - return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML, string.toString()); - } - } - case 300: - break; - case 116: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.BREAK, yytext()); - } - case 301: - break; - case 117: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CATCH, yytext()); - } - case 302: - break; - case 118: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONST, yytext()); - } - case 303: - break; - case 119: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CLASS, yytext()); - } - case 304: - break; - case 120: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SUPER, yytext()); - } - case 305: - break; - case 121: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TRACE, yytext()); - } - case 306: - break; - case 122: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THROW, yytext()); - } - case 307: - break; - case 123: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); - } - case 308: - break; - case 124: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WHILE, yytext()); - } - case 309: - break; - case 125: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINT, yytext()); - } - case 310: - break; - case 126: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBCHR, yytext()); - } - case 311: - break; - case 127: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBORD, yytext()); - } - case 312: - break; - case 128: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.RETURN, yytext()); - } - case 313: - break; - case 129: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.RANDOM, yytext()); - } - case 314: - break; - case 130: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.STATIC, yytext()); - } - case 315: - break; - case 131: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.SUBSTR, yytext()); - } - case 316: - break; - case 132: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SWITCH, yytext()); - } - case 317: - break; - case 133: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); - } - case 318: - break; - case 134: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPORT, yytext()); - } - case 319: - break; - case 135: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); - } - case 320: - break; - case 136: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LENGTH, yytext()); - } - case 321: - break; - case 137: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PUBLIC, yytext()); - } - case 322: - break; - case 138: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETURL, yytext()); - } - case 323: - break; - case 139: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STRING_OP, yytext()); - } - case 324: - break; - case 140: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.NUMBER_OP, yytext()); - } - case 325: - break; - case 141: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EXTENDS, yytext()); - } - case 326: - break; - case 142: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NEWLINE, yytext()); - } - case 327: - break; - case 143: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DEFAULT, yytext()); - } - case 328: - break; - case 144: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DYNAMIC, yytext()); - } - case 329: - break; - case 145: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FINALLY, yytext()); - } - case 330: - break; - case 146: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PRIVATE, yytext()); - } - case 331: - break; - case 147: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PACKAGE, yytext()); - } - case 332: - break; - case 148: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONTINUE, yytext()); - } - case 333: - break; - case 149: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOPDRAG, yytext()); - } - case 334: - break; - case 150: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.OVERRIDE, yytext()); - } - case 335: - break; - case 151: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERNAL, yytext()); - } - case 336: - break; - case 152: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FUNCTION, yytext()); - } - case 337: - break; - case 153: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTNUM, yytext()); - } - case 338: - break; - case 154: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBLENGTH, yytext()); - } - case 339: - break; - case 155: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETTIMER, yytext()); - } - case 340: - break; - case 156: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); - } - case 341: - break; - case 157: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STARTDRAG, yytext()); - } - case 342: - break; - case 158: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.NEXTFRAME, yytext()); - } - case 343: - break; - case 159: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.NAMESPACE, yytext()); - } - case 344: - break; - case 160: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERFACE, yytext()); - } - case 345: - break; - case 161: { - return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); - } - case 346: - break; - case 162: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.FSCOMMAND, yytext()); - } - case 347: - break; - case 163: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADMOVIE, yytext()); - } - case 348: - break; - case 164: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PREVFRAME, yytext()); - } - case 349: - break; - case 165: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PROTECTED, yytext()); - } - case 350: - break; - case 166: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TELLTARGET, yytext()); - } - case 351: - break; - case 167: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TARGETPATH, yytext()); - } - case 352: - break; - case 168: { - return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); - } - case 353: - break; - case 169: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPLEMENTS, yytext()); - } - case 354: - break; - case 170: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETVERSION, yytext()); - } - case 355: - break; - case 171: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIE, yytext()); - } - case 356: - break; - case 172: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBSUBSTRING, yytext()); - } - case 357: - break; - case 173: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GOTOANDSTOP, yytext()); - } - case 358: - break; - case 174: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GOTOANDPLAY, yytext()); - } - case 359: - break; - case 175: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADMOVIENUM, yytext()); - } - case 360: - break; - case 176: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOPALLSOUNDS, yytext()); - } - case 361: - break; - case 177: { - return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IFFRAMELOADED, yytext()); - } - case 362: - break; - case 178: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADVARIABLES, yytext()); - } - case 363: - break; - case 179: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTASBITMAP, yytext()); - } - case 364: - break; - case 180: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIENUM, yytext()); - } - case 365: - break; - case 181: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.REMOVEMOVIECLIP, yytext()); - } - case 366: - break; - case 182: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADVARIABLESNUM, yytext()); - } - case 367: - break; - case 183: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTASBITMAPNUM, yytext()); - } - case 368: - break; - case 184: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TOGGLEHIGHQUALITY, yytext()); - } - case 369: - break; - case 185: { - return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.DUPLICATEMOVIECLIP, yytext()); - } - case 370: - break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - { - return new ParsedSymbol(SymbolGroup.EOF, SymbolType.EOF, null); - } - } else { - zzScanError(ZZ_NO_MATCH); - } - } } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 1: + { + } + case 187: break; + case 2: + { yyline++; + } + case 188: break; + case 3: + { /*ignore*/ + } + case 189: break; + case 4: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DIVIDE, yytext()); + } + case 190: break; + case 5: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MULTIPLY, yytext()); + } + case 191: break; + case 6: + { return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, yytext()); + } + case 192: break; + case 7: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COLON, yytext()); + } + case 193: break; + case 8: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DOT, yytext()); + } + case 194: break; + case 9: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_THAN, yytext()); + } + case 195: break; + case 10: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_THAN, yytext()); + } + case 196: break; + case 11: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN, yytext()); + } + case 197: break; + case 12: + { string.setLength(0); + yybegin(STRING); + } + case 198: break; + case 13: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong((yytext()))); + } + case 199: break; + case 14: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MINUS, yytext()); + } + case 200: break; + case 15: + { string.setLength(0); + yybegin(CHARLITERAL); + } + case 201: break; + case 16: + { string.setLength(0); + yybegin(OIDENTIFIER); + } + case 202: break; + case 17: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_OPEN, yytext()); + } + case 203: break; + case 18: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PARENT_CLOSE, yytext()); + } + case 204: break; + case 19: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_OPEN, yytext()); + } + case 205: break; + case 20: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.CURLY_CLOSE, yytext()); + } + case 206: break; + case 21: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_OPEN, yytext()); + } + case 207: break; + case 22: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BRACKET_CLOSE, yytext()); + } + case 208: break; + case 23: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SEMICOLON, yytext()); + } + case 209: break; + case 24: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.COMMA, yytext()); + } + case 210: break; + case 25: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT, yytext()); + } + case 211: break; + case 26: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEGATE, yytext()); + } + case 212: break; + case 27: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TERNAR, yytext()); + } + case 213: break; + case 28: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITAND, yytext()); + } + case 214: break; + case 29: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.BITOR, yytext()); + } + case 215: break; + case 30: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.PLUS, yytext()); + } + case 216: break; + case 31: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.XOR, yytext()); + } + case 217: break; + case 32: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.MODULO, yytext()); + } + case 218: break; + case 33: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, yytext()); + } + case 219: break; + case 34: + { string.append(yytext()); + } + case 220: break; + case 35: + { yybegin(YYINITIAL); yyline++; + } + case 221: break; + case 36: + { yybegin(YYINITIAL); + // length also includes the trailing quote + return new ParsedSymbol(SymbolGroup.STRING, SymbolType.STRING, string.toString()); + } + case 222: break; + case 37: + { string.append(yytext()); yyline++; + } + case 223: break; + case 38: + { yybegin(XML); string.append(yytext()); + } + case 224: break; + case 39: + { string.append(yytext()); yyline++; + } + case 225: break; + case 40: + { yybegin(YYINITIAL); + // length also includes the trailing quote + return new ParsedSymbol(SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, string.toString()); + } + case 226: break; + case 41: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_DIVIDE, yytext()); + } + case 227: break; + case 42: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MULTIPLY, yytext()); + } + case 228: break; + case 43: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NAMESPACE_OP, yytext()); + } + case 229: break; + case 44: + { return new ParsedSymbol(SymbolGroup.DOUBLE, SymbolType.DOUBLE, Double.parseDouble((yytext()))); + } + case 230: break; + case 45: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_LEFT, yytext()); + } + case 231: break; + case 46: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NOT_EQUAL, yytext()); + } + case 232: break; + case 47: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.LOWER_EQUAL, yytext()); + } + case 233: break; + case 48: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.SHIFT_RIGHT, yytext()); + } + case 234: break; + case 49: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.GREATER_EQUAL, yytext()); + } + case 235: break; + case 50: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.EQUALS, yytext()); + } + case 236: break; + case 51: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext(), 8)); + } + case 237: break; + case 52: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MINUS, yytext()); + } + case 238: break; + case 53: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DECREMENT, yytext()); + } + case 239: break; + case 54: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AS, yytext()); + } + case 240: break; + case 55: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLOR, yytext()); + } + case 241: break; + case 56: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.IS, yytext()); + } + case 242: break; + case 57: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IN, yytext()); + } + case 243: break; + case 58: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IF, yytext()); + } + case 244: break; + case 59: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DO, yytext()); + } + case 245: break; + case 60: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITAND, yytext()); + } + case 246: break; + case 61: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.AND, yytext()); + } + case 247: break; + case 62: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_BITOR, yytext()); + } + case 248: break; + case 63: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.OR, yytext()); + } + case 249: break; + case 64: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_PLUS, yytext()); + } + case 250: break; + case 65: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INCREMENT, yytext()); + } + case 251: break; + case 66: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_XOR, yytext()); + } + case 252: break; + case 67: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_MODULO, yytext()); + } + case 253: break; + case 68: + { string.append('\\'); /*illegal escape sequence*/ + } + case 254: break; + case 69: + { string.append('\"'); + } + case 255: break; + case 70: + { string.append('\\'); + } + case 256: break; + case 71: + { string.append('\''); + } + case 257: break; + case 72: + { string.append('\b'); + } + case 258: break; + case 73: + { string.append('\r'); + } + case 259: break; + case 74: + { string.append('\n'); + } + case 260: break; + case 75: + { string.append('\t'); + } + case 261: break; + case 76: + { string.append('\f'); + } + case 262: break; + case 77: + { throw new ActionParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1); + } + case 263: break; + case 78: + { string.append('\u00A7'); + } + case 264: break; + case 79: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.REST, yytext()); + } + case 265: break; + case 80: + { string.setLength(0); + yybegin(XML); + String s = yytext(); + s = s.substring(1, s.length() - 1); + if (s.contains(" ")){ + s = s.substring(0, s.indexOf(' ')); + } + xmlTagName = s; + string.append(yytext()); + } + case 266: break; + case 81: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_LEFT, yytext()); + } + case 267: break; + case 82: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.USHIFT_RIGHT, yytext()); + } + case 268: break; + case 83: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_SHIFT_RIGHT, yytext()); + } + case 269: break; + case 84: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_EQUALS, yytext()); + } + case 270: break; + case 85: + { return new ParsedSymbol(SymbolGroup.INTEGER, SymbolType.INTEGER, Long.parseLong(yytext().substring(2), 16)); + } + case 271: break; + case 86: + { return new ParsedSymbol(SymbolGroup.PREPROCESSOR, SymbolType.PREPROCESSOR, yytext().substring(2)); + } + case 272: break; + case 87: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.FULLAND, yytext()); + } + case 273: break; + case 88: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.CHR, yytext()); + } + case 274: break; + case 89: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SET, yytext()); + } + case 275: break; + case 90: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.ORD, yytext()); + } + case 276: break; + case 91: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.NEW, yytext()); + } + case 277: break; + case 92: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRY, yytext()); + } + case 278: break; + case 93: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.INT, yytext()); + } + case 279: break; + case 94: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.USE, yytext()); + } + case 280: break; + case 95: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FOR, yytext()); + } + case 281: break; + case 96: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.VAR, yytext()); + } + case 282: break; + case 97: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.GET, yytext()); + } + case 283: break; + case 98: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NAN, yytext()); + } + case 284: break; + case 99: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.STRICT_NOT_EQUAL, yytext()); + } + case 285: break; + case 100: + { String t = yytext(); return new ParsedSymbol(SymbolGroup.TYPENAME, SymbolType.TYPENAME, t.substring(2, t.length() - 1)); + } + case 286: break; + case 101: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.ASSIGN_USHIFT_RIGHT, yytext()); + } + case 287: break; + case 102: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EACH, yytext()); + } + case 288: break; + case 103: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.ELSE, yytext()); + } + case 289: break; + case 104: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.EVAL, yytext()); + } + case 290: break; + case 105: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CASE, yytext()); + } + case 291: break; + case 106: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.CALL, yytext()); + } + case 292: break; + case 107: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOP, yytext()); + } + case 293: break; + case 108: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NULL, yytext()); + } + case 294: break; + case 109: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.TRUE, yytext()); + } + case 295: break; + case 110: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THIS, yytext()); + } + case 296: break; + case 111: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WITH, yytext()); + } + case 297: break; + case 112: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PLAY, yytext()); + } + case 298: break; + case 113: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.VOID, yytext()); + } + case 299: break; + case 114: + { char val = (char) Integer.parseInt(yytext().substring(1), 8); + string.append(val); + } + case 300: break; + case 115: + { char val = (char) Integer.parseInt(yytext().substring(2), 16); + string.append(val); + } + case 301: break; + case 116: + { string.append(yytext()); + String endtagname = yytext(); + endtagname = endtagname.substring(2, endtagname.length() - 1); + if (endtagname.equals(xmlTagName)){ + yybegin(YYINITIAL); + return new ParsedSymbol(SymbolGroup.XML, SymbolType.XML, string.toString()); + } + } + case 302: break; + case 117: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.BREAK, yytext()); + } + case 303: break; + case 118: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CATCH, yytext()); + } + case 304: break; + case 119: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONST, yytext()); + } + case 305: break; + case 120: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CLASS, yytext()); + } + case 306: break; + case 121: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SUPER, yytext()); + } + case 307: break; + case 122: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TRACE, yytext()); + } + case 308: break; + case 123: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.THROW, yytext()); + } + case 309: break; + case 124: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FALSE, yytext()); + } + case 310: break; + case 125: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.WHILE, yytext()); + } + case 311: break; + case 126: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINT, yytext()); + } + case 312: break; + case 127: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBCHR, yytext()); + } + case 313: break; + case 128: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBORD, yytext()); + } + case 314: break; + case 129: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.RETURN, yytext()); + } + case 315: break; + case 130: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.RANDOM, yytext()); + } + case 316: break; + case 131: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.STATIC, yytext()); + } + case 317: break; + case 132: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.SUBSTR, yytext()); + } + case 318: break; + case 133: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.SWITCH, yytext()); + } + case 319: break; + case 134: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.TYPEOF, yytext()); + } + case 320: break; + case 135: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPORT, yytext()); + } + case 321: break; + case 136: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.DELETE, yytext()); + } + case 322: break; + case 137: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LENGTH, yytext()); + } + case 323: break; + case 138: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PUBLIC, yytext()); + } + case 324: break; + case 139: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETURL, yytext()); + } + case 325: break; + case 140: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STRING_OP, yytext()); + } + case 326: break; + case 141: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.NUMBER_OP, yytext()); + } + case 327: break; + case 142: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.EXTENDS, yytext()); + } + case 328: break; + case 143: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.NEWLINE, yytext()); + } + case 329: break; + case 144: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DEFAULT, yytext()); + } + case 330: break; + case 145: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.DYNAMIC, yytext()); + } + case 331: break; + case 146: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FINALLY, yytext()); + } + case 332: break; + case 147: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PRIVATE, yytext()); + } + case 333: break; + case 148: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PACKAGE, yytext()); + } + case 334: break; + case 149: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.CONTINUE, yytext()); + } + case 335: break; + case 150: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOPDRAG, yytext()); + } + case 336: break; + case 151: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.OVERRIDE, yytext()); + } + case 337: break; + case 152: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERNAL, yytext()); + } + case 338: break; + case 153: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.FUNCTION, yytext()); + } + case 339: break; + case 154: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTNUM, yytext()); + } + case 340: break; + case 155: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBLENGTH, yytext()); + } + case 341: break; + case 156: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETTIMER, yytext()); + } + case 342: break; + case 157: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.INFINITY, yytext()); + } + case 343: break; + case 158: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STARTDRAG, yytext()); + } + case 344: break; + case 159: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.NEXTFRAME, yytext()); + } + case 345: break; + case 160: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.NAMESPACE, yytext()); + } + case 346: break; + case 161: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.INTERFACE, yytext()); + } + case 347: break; + case 162: + { return new ParsedSymbol(SymbolGroup.GLOBALCONST, SymbolType.UNDEFINED, yytext()); + } + case 348: break; + case 163: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.FSCOMMAND, yytext()); + } + case 349: break; + case 164: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADMOVIE, yytext()); + } + case 350: break; + case 165: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PREVFRAME, yytext()); + } + case 351: break; + case 166: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.PROTECTED, yytext()); + } + case 352: break; + case 167: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TELLTARGET, yytext()); + } + case 353: break; + case 168: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TARGETPATH, yytext()); + } + case 354: break; + case 169: + { return new ParsedSymbol(SymbolGroup.OPERATOR, SymbolType.INSTANCEOF, yytext()); + } + case 355: break; + case 170: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IMPLEMENTS, yytext()); + } + case 356: break; + case 171: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GETVERSION, yytext()); + } + case 357: break; + case 172: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIE, yytext()); + } + case 358: break; + case 173: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.MBSUBSTRING, yytext()); + } + case 359: break; + case 174: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GOTOANDSTOP, yytext()); + } + case 360: break; + case 175: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.GOTOANDPLAY, yytext()); + } + case 361: break; + case 176: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADMOVIENUM, yytext()); + } + case 362: break; + case 177: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.STOPALLSOUNDS, yytext()); + } + case 363: break; + case 178: + { return new ParsedSymbol(SymbolGroup.KEYWORD, SymbolType.IFFRAMELOADED, yytext()); + } + case 364: break; + case 179: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADVARIABLES, yytext()); + } + case 365: break; + case 180: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTASBITMAP, yytext()); + } + case 366: break; + case 181: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.UNLOADMOVIENUM, yytext()); + } + case 367: break; + case 182: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.REMOVEMOVIECLIP, yytext()); + } + case 368: break; + case 183: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.LOADVARIABLESNUM, yytext()); + } + case 369: break; + case 184: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.PRINTASBITMAPNUM, yytext()); + } + case 370: break; + case 185: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.TOGGLEHIGHQUALITY, yytext()); + } + case 371: break; + case 186: + { return new ParsedSymbol(SymbolGroup.GLOBALFUNC, SymbolType.DUPLICATEMOVIECLIP, yytext()); + } + case 372: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { + return new ParsedSymbol(SymbolGroup.EOF, SymbolType.EOF, null); + } + } + else { + zzScanError(ZZ_NO_MATCH); + } + } } + } + + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java index cceb4fb21..f8f203340 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java @@ -1,794 +1,806 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action.parser.script; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.FunctionActionItem; -import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; -import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; -import com.jpexs.decompiler.flash.action.model.operations.Inverted; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPop; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; -import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; -import com.jpexs.decompiler.flash.action.swf7.ActionExtends; -import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.helpers.collections.MyEntry; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.TypeItem; -import com.jpexs.decompiler.graph.model.AndItem; -import com.jpexs.decompiler.graph.model.BreakItem; -import com.jpexs.decompiler.graph.model.CommaExpressionItem; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.DoWhileItem; -import com.jpexs.decompiler.graph.model.DuplicateItem; -import com.jpexs.decompiler.graph.model.ForItem; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.NotItem; -import com.jpexs.decompiler.graph.model.OrItem; -import com.jpexs.decompiler.graph.model.SwitchItem; -import com.jpexs.decompiler.graph.model.TernarOpItem; -import com.jpexs.decompiler.graph.model.WhileItem; -import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class ActionSourceGenerator implements SourceGenerator { - - @Override - public List generate(SourceGeneratorLocalData localData, AndItem item) throws CompilationException { - List ret = new ArrayList<>(); - ret.addAll(generateToActionList(localData, item.leftSide)); - ret.add(new ActionPushDuplicate()); - ret.add(new ActionNot()); - List andExpr = generateToActionList(localData, item.rightSide); - andExpr.add(0, new ActionPop()); - int andExprLen = Action.actionsToBytes(andExpr, false, SWF.DEFAULT_VERSION).length; - ret.add(new ActionIf(andExprLen)); - ret.addAll(andExpr); - return ret; - - } - - @Override - public List generate(SourceGeneratorLocalData localData, OrItem item) throws CompilationException { - List ret = new ArrayList<>(); - ret.addAll(generateToActionList(localData, item.leftSide)); - ret.add(new ActionPushDuplicate()); - List orExpr = generateToActionList(localData, item.rightSide); - orExpr.add(0, new ActionPop()); - int orExprLen = Action.actionsToBytes(orExpr, false, SWF.DEFAULT_VERSION).length; - ret.add(new ActionIf(orExprLen)); - ret.addAll(orExpr); - return ret; - } - - public List toActionList(List items) { - List ret = new ArrayList<>(); - for (GraphSourceItem s : items) { - if (s instanceof Action) { - ret.add((Action) s); - } - } - return ret; - } - - private List nonempty(List list) { - if (list == null) { - return new ArrayList<>(); - } - return list; - } - - private List generateIf(SourceGeneratorLocalData localData, GraphTargetItem expression, List onTrueCmds, List onFalseCmds, boolean ternar) throws CompilationException { - List ret = new ArrayList<>(); - if (expression instanceof Inverted) { - ret.addAll(((Inverted) expression).invert().toSource(localData, this)); - } else { - ret.addAll(expression.toSource(localData, this)); - ret.add(new ActionNot()); - } - List onTrue = null; - List onFalse = null; - if (ternar) { - onTrue = toActionList(onTrueCmds.get(0).toSource(localData, this)); - } else { - onTrue = generateToActionList(localData, onTrueCmds); - } - - if (onFalseCmds != null && !onFalseCmds.isEmpty()) { - if (ternar) { - onFalse = toActionList(onFalseCmds.get(0).toSource(localData, this)); - } else { - onFalse = generateToActionList(localData, onFalseCmds); - } - } - byte[] onTrueBytes = Action.actionsToBytes(onTrue, false, SWF.DEFAULT_VERSION); - int onTrueLen = onTrueBytes.length; - - ActionIf ifaif = new ActionIf(0); - ret.add(ifaif); - ret.addAll(onTrue); - ifaif.setJumpOffset(onTrueLen); - ActionJump ajmp = null; - if (onFalse != null) { - if (!((!nonempty(onTrue).isEmpty()) - && (onTrue.get(onTrue.size() - 1) instanceof ActionJump) - && ((((ActionJump) onTrue.get(onTrue.size() - 1)).isContinue) - || (((ActionJump) onTrue.get(onTrue.size() - 1)).isBreak)))) { - ajmp = new ActionJump(0); - ret.add(ajmp); - onTrueLen += ajmp.getTotalActionLength(); - } - ifaif.setJumpOffset(onTrueLen); - byte[] onFalseBytes = Action.actionsToBytes(onFalse, false, SWF.DEFAULT_VERSION); - int onFalseLen = onFalseBytes.length; - if (ajmp != null) { - ajmp.setJumpOffset(onFalseLen); - } - ret.addAll(onFalse); - } - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, IfItem item) throws CompilationException { - return generateIf(localData, item.expression, item.onTrue, item.onFalse, false); - } - - private void fixLoop(List code, int breakOffset) { - fixLoop(code, breakOffset, Integer.MAX_VALUE); - } - - private void fixLoop(List code, int breakOffset, int continueOffset) { - int pos = 0; - for (Action a : code) { - pos += a.getTotalActionLength(); - if (a instanceof ActionJump) { - ActionJump aj = (ActionJump) a; - if (aj.isContinue && (continueOffset != Integer.MAX_VALUE)) { - aj.setJumpOffset(-pos + continueOffset); - aj.isContinue = false; - } - if (aj.isBreak) { - aj.setJumpOffset(-pos + breakOffset); - aj.isBreak = false; - } - } - } - } - - @Override - public List generate(SourceGeneratorLocalData localData, TernarOpItem item) throws CompilationException { - List onTrue = new ArrayList<>(); - onTrue.add(item.onTrue); - List onFalse = new ArrayList<>(); - onFalse.add(item.onFalse); - return generateIf(localData, item.expression, onTrue, onFalse, true); - } - - @Override - public List generate(SourceGeneratorLocalData localData, WhileItem item) throws CompilationException { - List ret = new ArrayList<>(); - List whileExpr = new ArrayList<>(); - - List ex = new ArrayList<>(item.expression); - if (!ex.isEmpty()) { - GraphTargetItem lastItem = ex.remove(ex.size() - 1); - whileExpr.addAll(generateToActionList(localData, ex)); - whileExpr.addAll(toActionList(lastItem.toSource(localData, this))); //Want result - } - - List whileBody = generateToActionList(localData, item.commands); - whileExpr.add(new ActionNot()); - ActionIf whileaif = new ActionIf(0); - whileExpr.add(whileaif); - ActionJump whileajmp = new ActionJump(0); - whileBody.add(whileajmp); - int whileExprLen = Action.actionsToBytes(whileExpr, false, SWF.DEFAULT_VERSION).length; - int whileBodyLen = Action.actionsToBytes(whileBody, false, SWF.DEFAULT_VERSION).length; - whileajmp.setJumpOffset(-(whileExprLen - + whileBodyLen)); - whileaif.setJumpOffset(whileBodyLen); - ret.addAll(whileExpr); - fixLoop(whileBody, whileBodyLen, -whileExprLen); - ret.addAll(whileBody); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, DoWhileItem item) throws CompilationException { - List ret = new ArrayList<>(); - List doExpr = generateToActionList(localData, item.expression); - List doBody = generateToActionList(localData, item.commands); - - int doBodyLen = Action.actionsToBytes(doBody, false, SWF.DEFAULT_VERSION).length; - int doExprLen = Action.actionsToBytes(doExpr, false, SWF.DEFAULT_VERSION).length; - - ret.addAll(doBody); - ret.addAll(doExpr); - ActionIf doif = new ActionIf(0); - ret.add(doif); - int offset = doBodyLen + doExprLen + doif.getTotalActionLength(); - doif.setJumpOffset(-offset); - fixLoop(doBody, offset, doBodyLen); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException { - List ret = new ArrayList<>(); - List forExpr = generateToActionList(localData, item.expression); - List forBody = generateToActionList(localData, item.commands); - List forFinalCommands = generateToActionList(localData, item.finalCommands); - - forExpr.add(new ActionNot()); - ActionIf foraif = new ActionIf(0); - forExpr.add(foraif); - ActionJump forajmp = new ActionJump(0); - int forajmpLen = forajmp.getTotalActionLength(); - int forExprLen = Action.actionsToBytes(forExpr, false, SWF.DEFAULT_VERSION).length; - int forBodyLen = Action.actionsToBytes(forBody, false, SWF.DEFAULT_VERSION).length; - int forFinalLen = Action.actionsToBytes(forFinalCommands, false, SWF.DEFAULT_VERSION).length; - forajmp.setJumpOffset(-(forExprLen - + forBodyLen + forFinalLen + forajmpLen)); - foraif.setJumpOffset(forBodyLen + forFinalLen + forajmpLen); - ret.addAll(forExpr); - ret.addAll(forBody); - ret.addAll(forFinalCommands); - ret.add(forajmp); - fixLoop(forBody, forBodyLen + forFinalLen + forajmpLen, forBodyLen); - return ret; - } - - private long uniqLast = 0; - - public String uniqId() { - uniqLast++; - return "" + uniqLast; - } - - @Override - public List generate(SourceGeneratorLocalData localData, SwitchItem item) throws CompilationException { - List ret = new ArrayList<>(); - HashMap registerVars = getRegisterVars(localData); - int exprReg = 0; - for (int i = 0; i < 256; i++) { - if (!registerVars.containsValue(i)) { - registerVars.put("__switch" + uniqId(), i); - exprReg = i; - break; - } - } - - ret.addAll(toActionList(item.switchedObject.toSource(localData, this))); - - boolean firstCase = true; - List> caseIfs = new ArrayList<>(); - List> caseCmds = new ArrayList<>(); - List>> caseExprsAll = new ArrayList<>(); - - loopm: - for (int m = 0; m < item.caseValues.size(); m++) { - List> caseExprs = new ArrayList<>(); - List caseIfsOne = new ArrayList<>(); - int mapping = item.valuesMapping.get(m); - for (; m < item.caseValues.size(); m++) { - int newmapping = item.valuesMapping.get(m); - if (newmapping != mapping) { - m--; - break; - } - List curCaseExpr = generateToActionList(localData, item.caseValues.get(m)); - caseExprs.add(curCaseExpr); - if (firstCase) { - curCaseExpr.add(0, new ActionStoreRegister(exprReg)); - } else { - curCaseExpr.add(0, new ActionPush(new RegisterNumber(exprReg))); - } - curCaseExpr.add(new ActionStrictEquals()); - ActionIf aif = new ActionIf(0); - caseIfsOne.add(aif); - curCaseExpr.add(aif); - ret.addAll(curCaseExpr); - firstCase = false; - } - caseExprsAll.add(caseExprs); - caseIfs.add(caseIfsOne); - List caseCmd = generateToActionList(localData, item.caseCommands.get(mapping)); - caseCmds.add(caseCmd); - } - ActionJump defJump = new ActionJump(0); - ret.add(defJump); - List defCmd = new ArrayList<>(); - if (!item.defaultCommands.isEmpty()) { - defCmd = generateToActionList(localData, item.defaultCommands); - } - for (List caseCmd : caseCmds) { - ret.addAll(caseCmd); - } - ret.addAll(defCmd); - - List> exprLengths = new ArrayList<>(); - for (List> caseExprs : caseExprsAll) { - List lengths = new ArrayList<>(); - for (List caseExpr : caseExprs) { - lengths.add(Action.actionsToBytes(caseExpr, false, SWF.DEFAULT_VERSION).length); - } - exprLengths.add(lengths); - } - List caseLengths = new ArrayList<>(); - for (List caseCmd : caseCmds) { - caseLengths.add(Action.actionsToBytes(caseCmd, false, SWF.DEFAULT_VERSION).length); - } - int defLength = Action.actionsToBytes(defCmd, false, SWF.DEFAULT_VERSION).length; - - for (int i = 0; i < caseIfs.size(); i++) { - for (int c = 0; c < caseIfs.get(i).size(); c++) { - int jmpPos = 0; - for (int j = c + 1; j < caseIfs.get(i).size(); j++) { - jmpPos += exprLengths.get(i).get(j); - } - for (int k = i + 1; k < caseIfs.size(); k++) { - for (int m = 0; m < caseIfs.get(k).size(); m++) { - jmpPos += exprLengths.get(k).get(m); - } - } - jmpPos += defJump.getTotalActionLength(); - for (int n = 0; n < i; n++) { - jmpPos += caseLengths.get(n); - } - caseIfs.get(i).get(c).setJumpOffset(jmpPos); - } - } - int defJmpPos = 0; - for (int i = 0; i < caseIfs.size(); i++) { - defJmpPos += caseLengths.get(i); - } - - defJump.setJumpOffset(defJmpPos); - List caseCmdsAll = new ArrayList<>(); - int breakOffset = 0; - for (int i = 0; i < caseCmds.size(); i++) { - caseCmdsAll.addAll(caseCmds.get(i)); - breakOffset += caseLengths.get(i); - } - breakOffset += defLength; - fixLoop(caseCmdsAll, breakOffset); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, NotItem item) throws CompilationException { - if (item.getOriginal() instanceof Inverted) { - GraphTargetItem norig = ((Inverted) item).invert(); - return norig.toSource(localData, this); - } - List ret = new ArrayList<>(); - ret.addAll(item.getOriginal().toSource(localData, this)); - ret.add(new ActionNot()); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, DuplicateItem item) { - List ret = new ArrayList<>(); - ret.add(new ActionPushDuplicate()); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, BreakItem item) { - List ret = new ArrayList<>(); - ActionJump abreak = new ActionJump(0); - abreak.isBreak = true; - ret.add(abreak); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, ContinueItem item) { - List ret = new ArrayList<>(); - ActionJump acontinue = new ActionJump(0); - acontinue.isContinue = true; - ret.add(acontinue); - return ret; - } - - private List generateToActionList(SourceGeneratorLocalData localData, List commands) throws CompilationException { - return toActionList(generate(localData, commands)); - } - - private List generateToActionList(SourceGeneratorLocalData localData, GraphTargetItem command) throws CompilationException { - return toActionList(command.toSource(localData, this)); - } - - @Override - public List generate(SourceGeneratorLocalData localData, List commands) throws CompilationException { - List ret = new ArrayList<>(); - for (GraphTargetItem item : commands) { - ret.addAll(item.toSourceIgnoreReturnValue(localData, this)); - } - return ret; - } - - public HashMap getRegisterVars(SourceGeneratorLocalData localData) { - return localData.registerVars; - } - - public void setRegisterVars(SourceGeneratorLocalData localData, HashMap value) { - localData.registerVars = value; - } - - public void setInFunction(SourceGeneratorLocalData localData, int value) { - localData.inFunction = value; - } - - public int isInFunction(SourceGeneratorLocalData localData) { - return localData.inFunction; - } - - public boolean isInMethod(SourceGeneratorLocalData localData) { - return localData.inMethod; - } - - public void setInMethod(SourceGeneratorLocalData localData, boolean value) { - localData.inMethod = value; - } - - public int getForInLevel(SourceGeneratorLocalData localData) { - return localData.forInLevel; - } - - public void setForInLevel(SourceGeneratorLocalData localData, int value) { - localData.forInLevel = value; - } - - public int getTempRegister(SourceGeneratorLocalData localData) { - HashMap registerVars = getRegisterVars(localData); - for (int tmpReg = 0; tmpReg < 256; tmpReg++) { - if (!registerVars.containsValue(tmpReg)) { - registerVars.put("__temp" + tmpReg, tmpReg); - return tmpReg; - } - } - return 0; //? - } - - public void releaseTempRegister(SourceGeneratorLocalData localData, int tmp) { - HashMap registerVars = getRegisterVars(localData); - registerVars.remove("__temp" + tmp); - } - - private String getName(GraphTargetItem item) { - if (item instanceof VariableActionItem) { - return ((VariableActionItem) item).getVariableName(); - } - if (item instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) item; - return (String) dv.getResult(); - } - if (item instanceof GetVariableActionItem) { - GetVariableActionItem gv = (GetVariableActionItem) item; - return getName(gv.name); - } - if (item instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) item; - return getName(mem.memberName); - } - return null; - } - - private List getVarParts(GraphTargetItem item) { - List ret = new ArrayList<>(); - do { - if (item instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) item; - ret.add(0, getName(mem)); - item = mem.object; - } - } while (item instanceof GetMemberActionItem); - String f = getName(item); - if (f != null) { - ret.add(0, f); - } - return ret; - } - - private int getVarLength(GraphTargetItem item) { - int len = 1; - do { - if (item instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) item; - item = mem.object; - len++; - } - } while (item instanceof GetMemberActionItem); - return len; - } - - private GraphTargetItem removeVarLast(GraphTargetItem item, int cnt) { - item = Helper.deepCopy(item); - - for (int i = 0; i < cnt; i++) { - if (item instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) item; - item = mem.object; - } - } - return item; - } - - private GraphTargetItem addGlobalPrefix(GraphTargetItem item) { - item = Helper.deepCopy(item); - GraphTargetItem first = item; - GetMemberActionItem mem = null; - do { - if (item instanceof GetMemberActionItem) { - mem = (GetMemberActionItem) item; - item = mem.object; - } - } while (item instanceof GetMemberActionItem); - if (item instanceof GetVariableActionItem) { - GetVariableActionItem v = (GetVariableActionItem) item; - item = new GetMemberActionItem(null, new GetVariableActionItem(null, new DirectValueActionItem(null, 0, "_global", new ArrayList<>())), v.name); - if (mem != null) { - mem.object = item; - } - } - return first; - } - - private List typeToActions(List type, List value) { - List ret = new ArrayList<>(); - if (type.isEmpty()) { - return ret; - } - ret.add(pushConst(type.get(0))); - if (type.size() == 1 && (value != null)) { - ret.addAll(value); - ret.add(new ActionSetVariable()); - } else { - ret.add(new ActionGetVariable()); - } - for (int i = 1; i < type.size(); i++) { - ret.add(pushConst(type.get(i))); - if ((i == type.size() - 1) && (value != null)) { - ret.addAll(value); - ret.add(new ActionSetMember()); - } else { - ret.add(new ActionGetMember()); - } - } - return ret; - } - - private final List constantPool; - - private final int swfVersion; - - public int getSwfVersion() { - return swfVersion; - } - - public ActionSourceGenerator(int swfVersion, List constantPool) { - this.constantPool = constantPool; - this.swfVersion = swfVersion; - } - - public List getConstantPool() { - return constantPool; - } - - public DirectValueActionItem pushConstTargetItem(String s) { - int index = constantPool.indexOf(s); - if (index == -1) { - constantPool.add(s); - index = constantPool.indexOf(s); - } - return new DirectValueActionItem(null, 0, new ConstantIndex(index), constantPool); - } - - public ActionPush pushConst(String s) { - int index = constantPool.indexOf(s); - if (index == -1) { - constantPool.add(s); - index = constantPool.indexOf(s); - } - return new ActionPush(new ConstantIndex(index)); - } - - public List generateTraits(SourceGeneratorLocalData localData, boolean isInterface, GraphTargetItem name, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List functions, List> vars, List staticFunctions, List> staticVars) throws CompilationException { - List extendsStr = getVarParts(extendsVal); - List ret = new ArrayList<>(); - List nameStr = getVarParts(name); - for (int i = 0; i < nameStr.size() - 1; i++) { - List notBody = new ArrayList<>(); - List globalClassTypeStr = new ArrayList<>(); - globalClassTypeStr.add("_global"); - for (int j = 0; j <= i; j++) { - globalClassTypeStr.add(nameStr.get(j)); - } - - List val = new ArrayList<>(); - val.add(new ActionPush((Long) 0L)); - val.add(pushConst("Object")); - val.add(new ActionNewObject()); - notBody.addAll(typeToActions(globalClassTypeStr, val)); - ret.addAll(typeToActions(globalClassTypeStr, null)); - ret.add(new ActionNot()); - ret.add(new ActionNot()); - ret.add(new ActionIf(Action.actionsToBytes(notBody, false, SWF.DEFAULT_VERSION).length)); - ret.addAll(notBody); - } - List ifbody = new ArrayList<>(); - List globalClassTypeStr = new ArrayList<>(); - globalClassTypeStr.add("_global"); - globalClassTypeStr.addAll(nameStr); - - ParsedSymbol s = null; - List constr = new ArrayList<>(); - - if (constructor == null) { - List val = new ArrayList<>(); - val.add(new ActionDefineFunction("", new ArrayList<>(), 0, SWF.DEFAULT_VERSION)); - if (!isInterface) { - val.add(new ActionStoreRegister(1)); - } - constr.addAll(typeToActions(globalClassTypeStr, val)); - } else { - constr.addAll(toActionList(((FunctionActionItem) constructor).toSource(localData, this))); - constr.add(new ActionStoreRegister(1)); - constr = (typeToActions(globalClassTypeStr, constr)); - } - if (!isInterface) { - for (GraphTargetItem f : staticFunctions) { - FunctionActionItem fi = (FunctionActionItem) f; - ifbody.add(new ActionPush(new RegisterNumber(1/*static*/))); - ifbody.add(new ActionPush(getName(fi.calculatedFunctionName))); - ifbody.addAll(toActionList(fi.toSource(localData, this))); - ifbody.add(new ActionSetMember()); - } - for (GraphTargetItem f : functions) { - FunctionActionItem fi = (FunctionActionItem) f; - ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/))); - ifbody.add(new ActionPush(getName(fi.calculatedFunctionName))); - ifbody.addAll(toActionList(fi.toSource(localData, this))); - ifbody.add(new ActionSetMember()); - } - for (MyEntry en : staticVars) { - ifbody.add(new ActionPush(new RegisterNumber(1/*static*/))); - ifbody.add(new ActionPush(getName(en.getKey()))); - ifbody.addAll(toActionList(en.getValue().toSource(localData, this))); - ifbody.add(new ActionSetMember()); - } - for (MyEntry en : vars) { - ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/))); - ifbody.add(new ActionPush(getName(en.getKey()))); - ifbody.addAll(toActionList(en.getValue().toSource(localData, this))); - ifbody.add(new ActionSetMember()); - } - } - - if (!isInterface) { - ifbody.add(new ActionPush((Long) 1L)); - ifbody.add(new ActionPush(new Null())); - ifbody.addAll(typeToActions(globalClassTypeStr, null)); - ifbody.add(pushConst("prototype")); - ifbody.add(new ActionGetMember()); - ifbody.add(new ActionPush((Long) 3L)); - ifbody.add(pushConst("ASSetPropFlags")); - ifbody.add(new ActionCallFunction()); - } - - if (constr.isEmpty()) { - List val = new ArrayList<>(); - val.add(new ActionDefineFunction("", new ArrayList<>(), 0, SWF.DEFAULT_VERSION)); - if (!isInterface) { - val.add(new ActionStoreRegister(1)); - } - constr.addAll(typeToActions(globalClassTypeStr, val)); - } - if (!extendsStr.isEmpty()) { - constr.addAll(typeToActions(globalClassTypeStr, null)); - constr.addAll(typeToActions(extendsStr, null)); - constr.add(new ActionExtends()); - } - if (!isInterface) { - constr.add(new ActionPush(new RegisterNumber(1))); - constr.add(pushConst("prototype")); - constr.add(new ActionGetMember()); - constr.add(new ActionStoreRegister(2)); - constr.add(new ActionPop()); - } - - if (!implementsStr.isEmpty()) { - for (GraphTargetItem imp : implementsStr) { - List impList = getVarParts(imp); - List globImp = new ArrayList<>(); - globImp.add("_global"); - globImp.addAll(impList); - constr.addAll(typeToActions(globImp, null)); - } - constr.add(new ActionPush((long) implementsStr.size())); - constr.addAll(typeToActions(globalClassTypeStr, null)); - constr.add(new ActionImplementsOp()); - } - ifbody.addAll(0, constr); - - ret.addAll(typeToActions(globalClassTypeStr, null)); - ret.add(new ActionNot()); - ret.add(new ActionNot()); - ret.add(new ActionIf(Action.actionsToBytes(ifbody, false, SWF.DEFAULT_VERSION).length)); - ret.addAll(ifbody); - ret.add(new ActionPop()); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, CommaExpressionItem item) throws CompilationException { - if (item.commands.isEmpty()) { - return new ArrayList<>(); - } - - //We need to handle commands and last expression separately, otherwise last expression result will be popped - List cmds = new ArrayList<>(item.commands); - GraphTargetItem lastExpr = cmds.remove(cmds.size() - 1); - List ret = new ArrayList<>(); - ret.addAll(generate(localData, cmds)); - ret.addAll(lastExpr.toSource(localData, this)); - return ret; - } - - @Override - public List generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException { - //Unsupported in AS1/2 - return new ArrayList<>(); - } - - @Override - public List generateDiscardValue(SourceGeneratorLocalData localData, GraphTargetItem item) throws CompilationException { - List ret = item.toSource(localData, this); - ret.add(new ActionPop()); - return ret; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action.parser.script; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.operations.Inverted; +import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPop; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; +import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; +import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; +import com.jpexs.decompiler.flash.action.swf7.ActionExtends; +import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.collections.MyEntry; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.model.AndItem; +import com.jpexs.decompiler.graph.model.BreakItem; +import com.jpexs.decompiler.graph.model.CommaExpressionItem; +import com.jpexs.decompiler.graph.model.ContinueItem; +import com.jpexs.decompiler.graph.model.DoWhileItem; +import com.jpexs.decompiler.graph.model.DuplicateItem; +import com.jpexs.decompiler.graph.model.FalseItem; +import com.jpexs.decompiler.graph.model.ForItem; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.OrItem; +import com.jpexs.decompiler.graph.model.SwitchItem; +import com.jpexs.decompiler.graph.model.TernarOpItem; +import com.jpexs.decompiler.graph.model.TrueItem; +import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.helpers.Helper; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class ActionSourceGenerator implements SourceGenerator { + + @Override + public List generate(SourceGeneratorLocalData localData, FalseItem item) throws CompilationException { + return GraphTargetItem.toSourceMerge(localData, this, new ActionPush(Boolean.FALSE)); + } + + @Override + public List generate(SourceGeneratorLocalData localData, TrueItem item) throws CompilationException { + return GraphTargetItem.toSourceMerge(localData, this, new ActionPush(Boolean.TRUE)); + } + + @Override + public List generate(SourceGeneratorLocalData localData, AndItem item) throws CompilationException { + List ret = new ArrayList<>(); + ret.addAll(generateToActionList(localData, item.leftSide)); + ret.add(new ActionPushDuplicate()); + ret.add(new ActionNot()); + List andExpr = generateToActionList(localData, item.rightSide); + andExpr.add(0, new ActionPop()); + int andExprLen = Action.actionsToBytes(andExpr, false, SWF.DEFAULT_VERSION).length; + ret.add(new ActionIf(andExprLen)); + ret.addAll(andExpr); + return ret; + + } + + @Override + public List generate(SourceGeneratorLocalData localData, OrItem item) throws CompilationException { + List ret = new ArrayList<>(); + ret.addAll(generateToActionList(localData, item.leftSide)); + ret.add(new ActionPushDuplicate()); + List orExpr = generateToActionList(localData, item.rightSide); + orExpr.add(0, new ActionPop()); + int orExprLen = Action.actionsToBytes(orExpr, false, SWF.DEFAULT_VERSION).length; + ret.add(new ActionIf(orExprLen)); + ret.addAll(orExpr); + return ret; + } + + public List toActionList(List items) { + List ret = new ArrayList<>(); + for (GraphSourceItem s : items) { + if (s instanceof Action) { + ret.add((Action) s); + } + } + return ret; + } + + private List nonempty(List list) { + if (list == null) { + return new ArrayList<>(); + } + return list; + } + + private List generateIf(SourceGeneratorLocalData localData, GraphTargetItem expression, List onTrueCmds, List onFalseCmds, boolean ternar) throws CompilationException { + List ret = new ArrayList<>(); + if (expression instanceof Inverted) { + ret.addAll(((Inverted) expression).invert(null).toSource(localData, this)); + } else { + ret.addAll(expression.toSource(localData, this)); + ret.add(new ActionNot()); + } + List onTrue = null; + List onFalse = null; + if (ternar) { + onTrue = toActionList(onTrueCmds.get(0).toSource(localData, this)); + } else { + onTrue = generateToActionList(localData, onTrueCmds); + } + + if (onFalseCmds != null && !onFalseCmds.isEmpty()) { + if (ternar) { + onFalse = toActionList(onFalseCmds.get(0).toSource(localData, this)); + } else { + onFalse = generateToActionList(localData, onFalseCmds); + } + } + byte[] onTrueBytes = Action.actionsToBytes(onTrue, false, SWF.DEFAULT_VERSION); + int onTrueLen = onTrueBytes.length; + + ActionIf ifaif = new ActionIf(0); + ret.add(ifaif); + ret.addAll(onTrue); + ifaif.setJumpOffset(onTrueLen); + ActionJump ajmp = null; + if (onFalse != null) { + if (!((!nonempty(onTrue).isEmpty()) + && (onTrue.get(onTrue.size() - 1) instanceof ActionJump) + && ((((ActionJump) onTrue.get(onTrue.size() - 1)).isContinue) + || (((ActionJump) onTrue.get(onTrue.size() - 1)).isBreak)))) { + ajmp = new ActionJump(0); + ret.add(ajmp); + onTrueLen += ajmp.getTotalActionLength(); + } + ifaif.setJumpOffset(onTrueLen); + byte[] onFalseBytes = Action.actionsToBytes(onFalse, false, SWF.DEFAULT_VERSION); + int onFalseLen = onFalseBytes.length; + if (ajmp != null) { + ajmp.setJumpOffset(onFalseLen); + } + ret.addAll(onFalse); + } + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, IfItem item) throws CompilationException { + return generateIf(localData, item.expression, item.onTrue, item.onFalse, false); + } + + private void fixLoop(List code, int breakOffset) { + fixLoop(code, breakOffset, Integer.MAX_VALUE); + } + + private void fixLoop(List code, int breakOffset, int continueOffset) { + int pos = 0; + for (Action a : code) { + pos += a.getTotalActionLength(); + if (a instanceof ActionJump) { + ActionJump aj = (ActionJump) a; + if (aj.isContinue && (continueOffset != Integer.MAX_VALUE)) { + aj.setJumpOffset(-pos + continueOffset); + aj.isContinue = false; + } + if (aj.isBreak) { + aj.setJumpOffset(-pos + breakOffset); + aj.isBreak = false; + } + } + } + } + + @Override + public List generate(SourceGeneratorLocalData localData, TernarOpItem item) throws CompilationException { + List onTrue = new ArrayList<>(); + onTrue.add(item.onTrue); + List onFalse = new ArrayList<>(); + onFalse.add(item.onFalse); + return generateIf(localData, item.expression, onTrue, onFalse, true); + } + + @Override + public List generate(SourceGeneratorLocalData localData, WhileItem item) throws CompilationException { + List ret = new ArrayList<>(); + List whileExpr = new ArrayList<>(); + + List ex = new ArrayList<>(item.expression); + if (!ex.isEmpty()) { + GraphTargetItem lastItem = ex.remove(ex.size() - 1); + whileExpr.addAll(generateToActionList(localData, ex)); + whileExpr.addAll(toActionList(lastItem.toSource(localData, this))); //Want result + } + + List whileBody = generateToActionList(localData, item.commands); + whileExpr.add(new ActionNot()); + ActionIf whileaif = new ActionIf(0); + whileExpr.add(whileaif); + ActionJump whileajmp = new ActionJump(0); + whileBody.add(whileajmp); + int whileExprLen = Action.actionsToBytes(whileExpr, false, SWF.DEFAULT_VERSION).length; + int whileBodyLen = Action.actionsToBytes(whileBody, false, SWF.DEFAULT_VERSION).length; + whileajmp.setJumpOffset(-(whileExprLen + + whileBodyLen)); + whileaif.setJumpOffset(whileBodyLen); + ret.addAll(whileExpr); + fixLoop(whileBody, whileBodyLen, -whileExprLen); + ret.addAll(whileBody); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, DoWhileItem item) throws CompilationException { + List ret = new ArrayList<>(); + List doExpr = generateToActionList(localData, item.expression); + List doBody = generateToActionList(localData, item.commands); + + int doBodyLen = Action.actionsToBytes(doBody, false, SWF.DEFAULT_VERSION).length; + int doExprLen = Action.actionsToBytes(doExpr, false, SWF.DEFAULT_VERSION).length; + + ret.addAll(doBody); + ret.addAll(doExpr); + ActionIf doif = new ActionIf(0); + ret.add(doif); + int offset = doBodyLen + doExprLen + doif.getTotalActionLength(); + doif.setJumpOffset(-offset); + fixLoop(doBody, offset, doBodyLen); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException { + List ret = new ArrayList<>(); + List forExpr = generateToActionList(localData, item.expression); + List forBody = generateToActionList(localData, item.commands); + List forFinalCommands = generateToActionList(localData, item.finalCommands); + + forExpr.add(new ActionNot()); + ActionIf foraif = new ActionIf(0); + forExpr.add(foraif); + ActionJump forajmp = new ActionJump(0); + int forajmpLen = forajmp.getTotalActionLength(); + int forExprLen = Action.actionsToBytes(forExpr, false, SWF.DEFAULT_VERSION).length; + int forBodyLen = Action.actionsToBytes(forBody, false, SWF.DEFAULT_VERSION).length; + int forFinalLen = Action.actionsToBytes(forFinalCommands, false, SWF.DEFAULT_VERSION).length; + forajmp.setJumpOffset(-(forExprLen + + forBodyLen + forFinalLen + forajmpLen)); + foraif.setJumpOffset(forBodyLen + forFinalLen + forajmpLen); + ret.addAll(forExpr); + ret.addAll(forBody); + ret.addAll(forFinalCommands); + ret.add(forajmp); + fixLoop(forBody, forBodyLen + forFinalLen + forajmpLen, forBodyLen); + return ret; + } + + private long uniqLast = 0; + + public String uniqId() { + uniqLast++; + return "" + uniqLast; + } + + @Override + public List generate(SourceGeneratorLocalData localData, SwitchItem item) throws CompilationException { + List ret = new ArrayList<>(); + HashMap registerVars = getRegisterVars(localData); + int exprReg = 0; + for (int i = 0; i < 256; i++) { + if (!registerVars.containsValue(i)) { + registerVars.put("__switch" + uniqId(), i); + exprReg = i; + break; + } + } + + ret.addAll(toActionList(item.switchedObject.toSource(localData, this))); + + boolean firstCase = true; + List> caseIfs = new ArrayList<>(); + List> caseCmds = new ArrayList<>(); + List>> caseExprsAll = new ArrayList<>(); + + loopm: + for (int m = 0; m < item.caseValues.size(); m++) { + List> caseExprs = new ArrayList<>(); + List caseIfsOne = new ArrayList<>(); + int mapping = item.valuesMapping.get(m); + for (; m < item.caseValues.size(); m++) { + int newmapping = item.valuesMapping.get(m); + if (newmapping != mapping) { + m--; + break; + } + List curCaseExpr = generateToActionList(localData, item.caseValues.get(m)); + caseExprs.add(curCaseExpr); + if (firstCase) { + curCaseExpr.add(0, new ActionStoreRegister(exprReg)); + } else { + curCaseExpr.add(0, new ActionPush(new RegisterNumber(exprReg))); + } + curCaseExpr.add(new ActionStrictEquals()); + ActionIf aif = new ActionIf(0); + caseIfsOne.add(aif); + curCaseExpr.add(aif); + ret.addAll(curCaseExpr); + firstCase = false; + } + caseExprsAll.add(caseExprs); + caseIfs.add(caseIfsOne); + List caseCmd = generateToActionList(localData, item.caseCommands.get(mapping)); + caseCmds.add(caseCmd); + } + ActionJump defJump = new ActionJump(0); + ret.add(defJump); + List defCmd = new ArrayList<>(); + if (!item.defaultCommands.isEmpty()) { + defCmd = generateToActionList(localData, item.defaultCommands); + } + for (List caseCmd : caseCmds) { + ret.addAll(caseCmd); + } + ret.addAll(defCmd); + + List> exprLengths = new ArrayList<>(); + for (List> caseExprs : caseExprsAll) { + List lengths = new ArrayList<>(); + for (List caseExpr : caseExprs) { + lengths.add(Action.actionsToBytes(caseExpr, false, SWF.DEFAULT_VERSION).length); + } + exprLengths.add(lengths); + } + List caseLengths = new ArrayList<>(); + for (List caseCmd : caseCmds) { + caseLengths.add(Action.actionsToBytes(caseCmd, false, SWF.DEFAULT_VERSION).length); + } + int defLength = Action.actionsToBytes(defCmd, false, SWF.DEFAULT_VERSION).length; + + for (int i = 0; i < caseIfs.size(); i++) { + for (int c = 0; c < caseIfs.get(i).size(); c++) { + int jmpPos = 0; + for (int j = c + 1; j < caseIfs.get(i).size(); j++) { + jmpPos += exprLengths.get(i).get(j); + } + for (int k = i + 1; k < caseIfs.size(); k++) { + for (int m = 0; m < caseIfs.get(k).size(); m++) { + jmpPos += exprLengths.get(k).get(m); + } + } + jmpPos += defJump.getTotalActionLength(); + for (int n = 0; n < i; n++) { + jmpPos += caseLengths.get(n); + } + caseIfs.get(i).get(c).setJumpOffset(jmpPos); + } + } + int defJmpPos = 0; + for (int i = 0; i < caseIfs.size(); i++) { + defJmpPos += caseLengths.get(i); + } + + defJump.setJumpOffset(defJmpPos); + List caseCmdsAll = new ArrayList<>(); + int breakOffset = 0; + for (int i = 0; i < caseCmds.size(); i++) { + caseCmdsAll.addAll(caseCmds.get(i)); + breakOffset += caseLengths.get(i); + } + breakOffset += defLength; + fixLoop(caseCmdsAll, breakOffset); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, NotItem item) throws CompilationException { + if (item.getOriginal() instanceof Inverted) { + GraphTargetItem norig = ((Inverted) item).invert(null); + return norig.toSource(localData, this); + } + List ret = new ArrayList<>(); + ret.addAll(item.getOriginal().toSource(localData, this)); + ret.add(new ActionNot()); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, DuplicateItem item) { + List ret = new ArrayList<>(); + ret.add(new ActionPushDuplicate()); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, BreakItem item) { + List ret = new ArrayList<>(); + ActionJump abreak = new ActionJump(0); + abreak.isBreak = true; + ret.add(abreak); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, ContinueItem item) { + List ret = new ArrayList<>(); + ActionJump acontinue = new ActionJump(0); + acontinue.isContinue = true; + ret.add(acontinue); + return ret; + } + + private List generateToActionList(SourceGeneratorLocalData localData, List commands) throws CompilationException { + return toActionList(generate(localData, commands)); + } + + private List generateToActionList(SourceGeneratorLocalData localData, GraphTargetItem command) throws CompilationException { + return toActionList(command.toSource(localData, this)); + } + + @Override + public List generate(SourceGeneratorLocalData localData, List commands) throws CompilationException { + List ret = new ArrayList<>(); + for (GraphTargetItem item : commands) { + ret.addAll(item.toSourceIgnoreReturnValue(localData, this)); + } + return ret; + } + + public HashMap getRegisterVars(SourceGeneratorLocalData localData) { + return localData.registerVars; + } + + public void setRegisterVars(SourceGeneratorLocalData localData, HashMap value) { + localData.registerVars = value; + } + + public void setInFunction(SourceGeneratorLocalData localData, int value) { + localData.inFunction = value; + } + + public int isInFunction(SourceGeneratorLocalData localData) { + return localData.inFunction; + } + + public boolean isInMethod(SourceGeneratorLocalData localData) { + return localData.inMethod; + } + + public void setInMethod(SourceGeneratorLocalData localData, boolean value) { + localData.inMethod = value; + } + + public int getForInLevel(SourceGeneratorLocalData localData) { + return localData.forInLevel; + } + + public void setForInLevel(SourceGeneratorLocalData localData, int value) { + localData.forInLevel = value; + } + + public int getTempRegister(SourceGeneratorLocalData localData) { + HashMap registerVars = getRegisterVars(localData); + for (int tmpReg = 0; tmpReg < 256; tmpReg++) { + if (!registerVars.containsValue(tmpReg)) { + registerVars.put("__temp" + tmpReg, tmpReg); + return tmpReg; + } + } + return 0; //? + } + + public void releaseTempRegister(SourceGeneratorLocalData localData, int tmp) { + HashMap registerVars = getRegisterVars(localData); + registerVars.remove("__temp" + tmp); + } + + private String getName(GraphTargetItem item) { + if (item instanceof VariableActionItem) { + return ((VariableActionItem) item).getVariableName(); + } + if (item instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) item; + return (String) dv.getResult(); + } + if (item instanceof GetVariableActionItem) { + GetVariableActionItem gv = (GetVariableActionItem) item; + return getName(gv.name); + } + if (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + return getName(mem.memberName); + } + return null; + } + + private List getVarParts(GraphTargetItem item) { + List ret = new ArrayList<>(); + do { + if (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + ret.add(0, getName(mem)); + item = mem.object; + } + } while (item instanceof GetMemberActionItem); + String f = getName(item); + if (f != null) { + ret.add(0, f); + } + return ret; + } + + private int getVarLength(GraphTargetItem item) { + int len = 1; + do { + if (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + item = mem.object; + len++; + } + } while (item instanceof GetMemberActionItem); + return len; + } + + private GraphTargetItem removeVarLast(GraphTargetItem item, int cnt) { + item = Helper.deepCopy(item); + + for (int i = 0; i < cnt; i++) { + if (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + item = mem.object; + } + } + return item; + } + + private GraphTargetItem addGlobalPrefix(GraphTargetItem item) { + item = Helper.deepCopy(item); + GraphTargetItem first = item; + GetMemberActionItem mem = null; + do { + if (item instanceof GetMemberActionItem) { + mem = (GetMemberActionItem) item; + item = mem.object; + } + } while (item instanceof GetMemberActionItem); + if (item instanceof GetVariableActionItem) { + GetVariableActionItem v = (GetVariableActionItem) item; + item = new GetMemberActionItem(null, new GetVariableActionItem(null, new DirectValueActionItem(null, 0, "_global", new ArrayList())), v.name); + if (mem != null) { + mem.object = item; + } + } + return first; + } + + private List typeToActions(List type, List value) { + List ret = new ArrayList<>(); + if (type.isEmpty()) { + return ret; + } + ret.add(pushConst(type.get(0))); + if (type.size() == 1 && (value != null)) { + ret.addAll(value); + ret.add(new ActionSetVariable()); + } else { + ret.add(new ActionGetVariable()); + } + for (int i = 1; i < type.size(); i++) { + ret.add(pushConst(type.get(i))); + if ((i == type.size() - 1) && (value != null)) { + ret.addAll(value); + ret.add(new ActionSetMember()); + } else { + ret.add(new ActionGetMember()); + } + } + return ret; + } + + private final List constantPool; + + private final int swfVersion; + + public int getSwfVersion() { + return swfVersion; + } + + public ActionSourceGenerator(int swfVersion, List constantPool) { + this.constantPool = constantPool; + this.swfVersion = swfVersion; + } + + public List getConstantPool() { + return constantPool; + } + + public DirectValueActionItem pushConstTargetItem(String s) { + int index = constantPool.indexOf(s); + if (index == -1) { + constantPool.add(s); + index = constantPool.indexOf(s); + } + return new DirectValueActionItem(null, 0, new ConstantIndex(index), constantPool); + } + + public ActionPush pushConst(String s) { + int index = constantPool.indexOf(s); + if (index == -1) { + constantPool.add(s); + index = constantPool.indexOf(s); + } + return new ActionPush(new ConstantIndex(index)); + } + + public List generateTraits(SourceGeneratorLocalData localData, boolean isInterface, GraphTargetItem name, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List functions, List> vars, List staticFunctions, List> staticVars) throws CompilationException { + List extendsStr = getVarParts(extendsVal); + List ret = new ArrayList<>(); + List nameStr = getVarParts(name); + for (int i = 0; i < nameStr.size() - 1; i++) { + List notBody = new ArrayList<>(); + List globalClassTypeStr = new ArrayList<>(); + globalClassTypeStr.add("_global"); + for (int j = 0; j <= i; j++) { + globalClassTypeStr.add(nameStr.get(j)); + } + + List val = new ArrayList<>(); + val.add(new ActionPush((Long) 0L)); + val.add(pushConst("Object")); + val.add(new ActionNewObject()); + notBody.addAll(typeToActions(globalClassTypeStr, val)); + ret.addAll(typeToActions(globalClassTypeStr, null)); + ret.add(new ActionNot()); + ret.add(new ActionNot()); + ret.add(new ActionIf(Action.actionsToBytes(notBody, false, SWF.DEFAULT_VERSION).length)); + ret.addAll(notBody); + } + List ifbody = new ArrayList<>(); + List globalClassTypeStr = new ArrayList<>(); + globalClassTypeStr.add("_global"); + globalClassTypeStr.addAll(nameStr); + + ParsedSymbol s = null; + List constr = new ArrayList<>(); + + if (constructor == null) { + List val = new ArrayList<>(); + val.add(new ActionDefineFunction("", new ArrayList(), 0, SWF.DEFAULT_VERSION)); + if (!isInterface) { + val.add(new ActionStoreRegister(1)); + } + constr.addAll(typeToActions(globalClassTypeStr, val)); + } else { + constr.addAll(toActionList(((FunctionActionItem) constructor).toSource(localData, this))); + constr.add(new ActionStoreRegister(1)); + constr = (typeToActions(globalClassTypeStr, constr)); + } + if (!isInterface) { + for (GraphTargetItem f : staticFunctions) { + FunctionActionItem fi = (FunctionActionItem) f; + ifbody.add(new ActionPush(new RegisterNumber(1/*static*/))); + ifbody.add(new ActionPush(getName(fi.calculatedFunctionName))); + ifbody.addAll(toActionList(fi.toSource(localData, this))); + ifbody.add(new ActionSetMember()); + } + for (GraphTargetItem f : functions) { + FunctionActionItem fi = (FunctionActionItem) f; + ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/))); + ifbody.add(new ActionPush(getName(fi.calculatedFunctionName))); + ifbody.addAll(toActionList(fi.toSource(localData, this))); + ifbody.add(new ActionSetMember()); + } + for (MyEntry en : staticVars) { + ifbody.add(new ActionPush(new RegisterNumber(1/*static*/))); + ifbody.add(new ActionPush(getName(en.getKey()))); + ifbody.addAll(toActionList(en.getValue().toSource(localData, this))); + ifbody.add(new ActionSetMember()); + } + for (MyEntry en : vars) { + ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/))); + ifbody.add(new ActionPush(getName(en.getKey()))); + ifbody.addAll(toActionList(en.getValue().toSource(localData, this))); + ifbody.add(new ActionSetMember()); + } + } + + if (!isInterface) { + ifbody.add(new ActionPush((Long) 1L)); + ifbody.add(new ActionPush(new Null())); + ifbody.addAll(typeToActions(globalClassTypeStr, null)); + ifbody.add(pushConst("prototype")); + ifbody.add(new ActionGetMember()); + ifbody.add(new ActionPush((Long) 3L)); + ifbody.add(pushConst("ASSetPropFlags")); + ifbody.add(new ActionCallFunction()); + } + + if (constr.isEmpty()) { + List val = new ArrayList<>(); + val.add(new ActionDefineFunction("", new ArrayList(), 0, SWF.DEFAULT_VERSION)); + if (!isInterface) { + val.add(new ActionStoreRegister(1)); + } + constr.addAll(typeToActions(globalClassTypeStr, val)); + } + if (!extendsStr.isEmpty()) { + constr.addAll(typeToActions(globalClassTypeStr, null)); + constr.addAll(typeToActions(extendsStr, null)); + constr.add(new ActionExtends()); + } + if (!isInterface) { + constr.add(new ActionPush(new RegisterNumber(1))); + constr.add(pushConst("prototype")); + constr.add(new ActionGetMember()); + constr.add(new ActionStoreRegister(2)); + constr.add(new ActionPop()); + } + + if (!implementsStr.isEmpty()) { + for (GraphTargetItem imp : implementsStr) { + List impList = getVarParts(imp); + List globImp = new ArrayList<>(); + globImp.add("_global"); + globImp.addAll(impList); + constr.addAll(typeToActions(globImp, null)); + } + constr.add(new ActionPush((long) implementsStr.size())); + constr.addAll(typeToActions(globalClassTypeStr, null)); + constr.add(new ActionImplementsOp()); + } + ifbody.addAll(0, constr); + + ret.addAll(typeToActions(globalClassTypeStr, null)); + ret.add(new ActionNot()); + ret.add(new ActionNot()); + ret.add(new ActionIf(Action.actionsToBytes(ifbody, false, SWF.DEFAULT_VERSION).length)); + ret.addAll(ifbody); + ret.add(new ActionPop()); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, CommaExpressionItem item) throws CompilationException { + if (item.commands.isEmpty()) { + return new ArrayList<>(); + } + + //We need to handle commands and last expression separately, otherwise last expression result will be popped + List cmds = new ArrayList<>(item.commands); + GraphTargetItem lastExpr = cmds.remove(cmds.size() - 1); + List ret = new ArrayList<>(); + ret.addAll(generate(localData, cmds)); + ret.addAll(lastExpr.toSource(localData, this)); + return ret; + } + + @Override + public List generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException { + //Unsupported in AS1/2 + return new ArrayList<>(); + } + + @Override + public List generateDiscardValue(SourceGeneratorLocalData localData, GraphTargetItem item) throws CompilationException { + List ret = item.toSource(localData, this); + ret.add(new ActionPop()); + return ret; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java index 6b162a4fd..afc76fa4f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolGroup.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.parser.script; /** @@ -32,5 +33,6 @@ public enum SymbolGroup { TYPENAME, EOF, GLOBALFUNC, - GLOBALCONST + GLOBALCONST, + PREPROCESSOR } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java index 7e46c3ce5..4493f9c3d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java @@ -1,222 +1,223 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action.parser.script; - -import com.jpexs.decompiler.graph.GraphTargetItem; - -/** - * - * @author JPEXS - */ -public enum SymbolType { - //Keywords - - BREAK, - CASE, - CONTINUE, - DEFAULT, - DO, - WHILE, - ELSE, - FOR, - EACH, - IN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IF, - RETURN, - SUPER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SWITCH, - THROW, - TRY, - CATCH, - FINALLY, - WITH, - DYNAMIC, - INTERNAL, - OVERRIDE, - PRIVATE, - PROTECTED, - PUBLIC, - STATIC, - CLASS, - CONST, - EXTENDS, - FUNCTION(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GET, - IMPLEMENTS, - INTERFACE, - NAMESPACE, - PACKAGE, - SET, - VAR, - IMPORT, - USE, - FALSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NULL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - THIS(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TRUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //Operators - PARENT_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PARENT_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SEMICOLON, - COMMA(GraphTargetItem.PRECEDENCE_COMMA, false), - REST, - DOT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - ASSIGN(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - GREATER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - LOWER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT(GraphTargetItem.PRECEDENCE_UNARY, false), - NEGATE(GraphTargetItem.PRECEDENCE_UNARY, false), - TERNAR(GraphTargetItem.PRECEDENCE_CONDITIONAL, true, true), /*!! ternar !!!*/ - COLON(GraphTargetItem.PRECEDENCE_CONDITIONAL, false),/*!! ternar !!!*/ - EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - LOWER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - GREATER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - AND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), - OR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), - FULLAND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), - FULLOR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), - INCREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false),//OR Unary - DECREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false), //OR Unary - PLUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), - MINUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), //OR Unary - MULTIPLY(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - DIVIDE(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - BITAND(GraphTargetItem.PRECEDENCE_BITWISEAND, true), - BITOR(GraphTargetItem.PRECEDENCE_BITWISEOR, true), - XOR(GraphTargetItem.PRECEDENCE_BITWISEXOR, true), - MODULO(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_LEFT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - ASSIGN_PLUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MINUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MULTIPLY(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_DIVIDE(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITAND(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_XOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MODULO(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_LEFT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - AS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - DELETE(GraphTargetItem.PRECEDENCE_UNARY, false), - INSTANCEOF(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NAMESPACE_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEW(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPEOF(GraphTargetItem.PRECEDENCE_UNARY, false), - VOID, - ATTRIBUTE, - //Other - STRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), - COMMENT, - XML, - IDENTIFIER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - INTEGER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - DOUBLE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - EOF, - TRACE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GETURL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GOTOANDSTOP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEXTFRAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PLAY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PREVFRAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TELLTARGET(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STOP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STOPALLSOUNDS(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TOGGLEHIGHQUALITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - ORD(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CHR(GraphTargetItem.PRECEDENCE_PRIMARY, false), - DUPLICATEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STOPDRAG(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GETTIMER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LOADVARIABLES(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GOTOANDPLAY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - MBORD(GraphTargetItem.PRECEDENCE_PRIMARY, false), - MBCHR(GraphTargetItem.PRECEDENCE_PRIMARY, false), - MBLENGTH(GraphTargetItem.PRECEDENCE_PRIMARY, false), - MBSUBSTRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), - RANDOM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - REMOVEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STARTDRAG(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SUBSTR(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LENGTH(GraphTargetItem.PRECEDENCE_PRIMARY, false), //string.length - INT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TARGETPATH(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NUMBER_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STRING_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - IFFRAMELOADED, - INFINITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - EVAL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - UNDEFINED(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEWLINE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NAN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GETVERSION(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CALL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - LOADVARIABLESNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PRINT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PRINTNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PRINTASBITMAP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PRINTASBITMAPNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - UNLOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - UNLOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), - FSCOMMAND(GraphTargetItem.PRECEDENCE_PRIMARY, false); - - private int precedence = GraphTargetItem.NOPRECEDENCE; - - private boolean binary = false; - - private boolean rightAssociative = false; - - public boolean isBinary() { - return binary; - } - - public boolean isRightAssociative() { - return rightAssociative; - } - - public int getPrecedence() { - return precedence; - } - - private SymbolType(int precedence, boolean binary) { - this.precedence = precedence; - this.binary = binary; - } - - private SymbolType(int precedence, boolean binary, boolean rightAssociative) { - this.precedence = precedence; - this.binary = binary; - this.rightAssociative = rightAssociative; - } - - private SymbolType() { - - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action.parser.script; + +import com.jpexs.decompiler.graph.GraphTargetItem; + +/** + * + * @author JPEXS + */ +public enum SymbolType { + //Keywords + + BREAK, + CASE, + CONTINUE, + DEFAULT, + DO, + WHILE, + ELSE, + FOR, + EACH, + IN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + IF, + RETURN, + SUPER(GraphTargetItem.PRECEDENCE_PRIMARY, false), + SWITCH, + THROW, + TRY, + CATCH, + FINALLY, + WITH, + DYNAMIC, + INTERNAL, + OVERRIDE, + PRIVATE, + PROTECTED, + PUBLIC, + STATIC, + CLASS, + CONST, + EXTENDS, + FUNCTION(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GET, + IMPLEMENTS, + INTERFACE, + NAMESPACE, + PACKAGE, + SET, + VAR, + IMPORT, + USE, + FALSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NULL(GraphTargetItem.PRECEDENCE_PRIMARY, false), + THIS(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TRUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + //Operators + PARENT_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PARENT_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + CURLY_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), + CURLY_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + BRACKET_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), + BRACKET_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + SEMICOLON, + COMMA(GraphTargetItem.PRECEDENCE_COMMA, false), + REST, + DOT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + ASSIGN(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + GREATER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + LOWER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + NOT(GraphTargetItem.PRECEDENCE_UNARY, false), + NEGATE(GraphTargetItem.PRECEDENCE_UNARY, false), + TERNAR(GraphTargetItem.PRECEDENCE_CONDITIONAL, true, true), /*!! ternar !!!*/ + COLON(GraphTargetItem.PRECEDENCE_CONDITIONAL, false),/*!! ternar !!!*/ + EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), + STRICT_EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), + LOWER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + GREATER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), + STRICT_NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), + AND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), + OR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), + FULLAND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), + FULLOR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), + INCREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false),//OR Unary + DECREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false), //OR Unary + PLUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), + MINUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), //OR Unary + MULTIPLY(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), + DIVIDE(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), + BITAND(GraphTargetItem.PRECEDENCE_BITWISEAND, true), + BITOR(GraphTargetItem.PRECEDENCE_BITWISEOR, true), + XOR(GraphTargetItem.PRECEDENCE_BITWISEXOR, true), + MODULO(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), + SHIFT_LEFT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), + SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), + USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), + ASSIGN_PLUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_MINUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_MULTIPLY(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_DIVIDE(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_BITAND(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_BITOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_XOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_MODULO(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_SHIFT_LEFT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + ASSIGN_USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), + AS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + DELETE(GraphTargetItem.PRECEDENCE_UNARY, false), + INSTANCEOF(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + IS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), + NAMESPACE_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NEW(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TYPEOF(GraphTargetItem.PRECEDENCE_UNARY, false), + VOID, + ATTRIBUTE, + //Other + STRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), + COMMENT, + XML, + IDENTIFIER(GraphTargetItem.PRECEDENCE_PRIMARY, false), + INTEGER(GraphTargetItem.PRECEDENCE_PRIMARY, false), + DOUBLE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TYPENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), + EOF, + TRACE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GETURL(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GOTOANDSTOP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NEXTFRAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PLAY(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PREVFRAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TELLTARGET(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STOP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STOPALLSOUNDS(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TOGGLEHIGHQUALITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), + ORD(GraphTargetItem.PRECEDENCE_PRIMARY, false), + CHR(GraphTargetItem.PRECEDENCE_PRIMARY, false), + DUPLICATEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STOPDRAG(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GETTIMER(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LOADVARIABLES(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GOTOANDPLAY(GraphTargetItem.PRECEDENCE_PRIMARY, false), + MBORD(GraphTargetItem.PRECEDENCE_PRIMARY, false), + MBCHR(GraphTargetItem.PRECEDENCE_PRIMARY, false), + MBLENGTH(GraphTargetItem.PRECEDENCE_PRIMARY, false), + MBSUBSTRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), + RANDOM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + REMOVEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STARTDRAG(GraphTargetItem.PRECEDENCE_PRIMARY, false), + SUBSTR(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LENGTH(GraphTargetItem.PRECEDENCE_PRIMARY, false), //string.length + INT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + TARGETPATH(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NUMBER_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + STRING_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + IFFRAMELOADED, + INFINITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), + EVAL(GraphTargetItem.PRECEDENCE_PRIMARY, false), + UNDEFINED(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NEWLINE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + NAN(GraphTargetItem.PRECEDENCE_PRIMARY, false), + GETVERSION(GraphTargetItem.PRECEDENCE_PRIMARY, false), + CALL(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + LOADVARIABLESNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PRINT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PRINTNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PRINTASBITMAP(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PRINTASBITMAPNUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + UNLOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY, false), + UNLOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY, false), + FSCOMMAND(GraphTargetItem.PRECEDENCE_PRIMARY, false), + PREPROCESSOR(GraphTargetItem.PRECEDENCE_PRIMARY, false); + + private int precedence = GraphTargetItem.NOPRECEDENCE; + + private boolean binary = false; + + private boolean rightAssociative = false; + + public boolean isBinary() { + return binary; + } + + public boolean isRightAssociative() { + return rightAssociative; + } + + public int getPrecedence() { + return precedence; + } + + private SymbolType(int precedence, boolean binary) { + this.precedence = precedence; + this.binary = binary; + } + + private SymbolType(int precedence, boolean binary, boolean rightAssociative) { + this.precedence = precedence; + this.binary = binary; + this.rightAssociative = rightAssociative; + } + + private SymbolType() { + + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java index 93f887a6c..339791567 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionNot.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.swf4; import com.jpexs.decompiler.flash.action.Action; @@ -36,6 +37,6 @@ public class ActionNot extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { GraphTargetItem a = stack.pop(); - stack.push(new NotItem(this, a)); + stack.push(a.invert(this)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java index 4156119da..d95cc43c2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.swf4; import com.jpexs.decompiler.flash.action.Action; @@ -35,13 +36,7 @@ public class ActionPop extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { - if (stack.isEmpty()) { - return; - } GraphTargetItem val = stack.pop(); - if (val instanceof DirectValueActionItem) { - return; - } output.add(val); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java index ab88fd0e1..9b9a790f0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java @@ -37,6 +37,8 @@ import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.FalseItem; +import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.helpers.Helper; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -360,18 +362,27 @@ public class ActionPush extends Action { } } }*/ - DirectValueActionItem dvt = new DirectValueActionItem(this, pos, o, constantPool); - - if (o instanceof RegisterNumber) {//TemporaryRegister - dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); - if (regNames.containsKey(((RegisterNumber) o).number)) { - ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); + if (o instanceof Boolean) { + Boolean b = (Boolean) o; + if (b) { + stack.push(new TrueItem(this)); + } else { + stack.push(new FalseItem(this)); } - } - if (dvt.computedRegValue instanceof TemporaryRegister) { - stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value)); } else { - stack.push(dvt); + DirectValueActionItem dvt = new DirectValueActionItem(this, pos, o, constantPool); + + if (o instanceof RegisterNumber) {//TemporaryRegister + dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); + if (regNames.containsKey(((RegisterNumber) o).number)) { + ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); + } + } + if (dvt.computedRegValue instanceof TemporaryRegister) { + stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value)); + } else { + stack.push(dvt); + } } pos++; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java index d2332ea9d..fb5e7bf96 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.swf5; import com.jpexs.decompiler.flash.action.Action; @@ -39,7 +40,7 @@ public class ActionEnumerate extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { GraphTargetItem object = stack.pop(); - stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList<>())); - stack.push(new EnumerateActionItem(this, object)); + //stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList())); + output.add(new EnumerateActionItem(this, object)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java index 5ffa6770f..f00e5bc70 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java @@ -12,13 +12,15 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.swf5; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.graph.GraphSourceItemPos; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.DuplicateItem; import java.util.HashMap; import java.util.List; @@ -36,7 +38,7 @@ public class ActionPushDuplicate extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { GraphTargetItem value = stack.peek(); - stack.push(value); + stack.push(new DuplicateItem(this, value)); value.moreSrc.add(new GraphSourceItemPos(this, 0)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java index fd05ef6e7..9e56b1868 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java @@ -1,42 +1,42 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action.swf6; - -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class ActionEnumerate2 extends Action { - - public ActionEnumerate2() { - super(0x55, 0); - } - - @Override - public String toString() { - return "Enumerate2"; - } - - @Override - public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { - GraphTargetItem object = stack.pop(); - stack.push(new EnumerateActionItem(this, object)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action.swf6; + +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class ActionEnumerate2 extends Action { + + public ActionEnumerate2() { + super(0x55, 0); + } + + @Override + public String toString() { + return "Enumerate2"; + } + + @Override + public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { + GraphTargetItem object = stack.pop(); + output.add(new EnumerateActionItem(this, object)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 620b9dd18..ad8d72a54 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -16,6 +16,8 @@ */ package com.jpexs.decompiler.graph; +import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.flash.BaseLocalData; import com.jpexs.decompiler.flash.FinalProcessLocalData; import com.jpexs.decompiler.flash.action.Action; @@ -25,7 +27,9 @@ import com.jpexs.decompiler.graph.model.AndItem; import com.jpexs.decompiler.graph.model.BreakItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.DoWhileItem; +import com.jpexs.decompiler.graph.model.DuplicateItem; import com.jpexs.decompiler.graph.model.ExitItem; +import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.ForItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.IntegerValueItem; @@ -37,8 +41,10 @@ import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.ScriptEndItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; +import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.decompiler.graph.model.UniversalLoopItem; import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.helpers.Helper; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -422,7 +428,7 @@ public class Graph { for (GraphPart head : heads) { populateParts(head, allParts); } - TranslateStack stack = new TranslateStack(); + TranslateStack stack = new TranslateStack(path); List loops = new ArrayList<>(); getLoops(localData, heads.get(0), loops, null); /*System.out.println(""); @@ -461,8 +467,59 @@ public class Graph { finalProcessAfter(list, level, localData); } - protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData) { + private boolean processSubBlk(Block b, GraphTargetItem replacement) { + boolean allSubPush = true; + boolean atleastOne = false; + for (List sub : b.getSubs()) { + if (!sub.isEmpty()) { + int lastPos = sub.size() - 1; + GraphTargetItem last = sub.get(sub.size() - 1); + GraphTargetItem br = null; + + if ((last instanceof BreakItem) && (sub.size() >= 2)) { + br = last; + lastPos--; + last = sub.get(lastPos); + } + if (last instanceof Block) { + if (!processSubBlk((Block) last, replacement)) { + allSubPush = false; + } else { + atleastOne = true; + } + } else if (last instanceof PushItem) { + if (replacement != null) { + GraphTargetItem e2 = (((GraphTargetItem) replacement).clone()); + e2.value = last.value; + sub.set(lastPos, e2); + if (br != null) { + sub.remove(sub.size() - 1); + } + } + atleastOne = true; + } else if (!(last instanceof ExitItem)) { + allSubPush = false; + } + } + } + return allSubPush && atleastOne; + } + + protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData) { + if (list.size() >= 2) { + if (list.get(list.size() - 1) instanceof ExitItem) { + ExitItem e = (ExitItem) list.get(list.size() - 1); + if (list.get(list.size() - 1).value instanceof PopItem) { + if (list.get(list.size() - 2) instanceof Block) { + Block b = (Block) list.get(list.size() - 2); + if (processSubBlk(b, (GraphTargetItem) e)) { + list.remove(list.size() - 1); + } + } + } + } + } } protected void finalProcess(List list, int level, FinalProcessLocalData localData) { @@ -527,7 +584,7 @@ public class Graph { } private void processIfs(List list) { - //if(true) return; + for (int i = 0; i < list.size(); i++) { GraphTargetItem item = list.get(i); if (item instanceof Block) { @@ -1382,7 +1439,11 @@ public class Graph { } List currentRet = ret; UniversalLoopItem loopItem = null; + TranslateStack sPreLoop = stack; if (isLoop) { + //makeAllCommands(currentRet, stack); + stack = (TranslateStack) stack.clone(); + stack.clear(); loopItem = new UniversalLoopItem(null, currentLoop); //loopItem.commands=printGraph(visited, localData, stack, allParts, parent, part, stopPart, loops); currentRet.add(loopItem); @@ -1412,23 +1473,6 @@ public class Graph { } } - //Assuming part with two nextparts is an IF - - /* //If with both branches empty - if (part.nextParts.size() == 2) { - if (part.nextParts.get(0) == part.nextParts.get(1)) { - if (!stack.isEmpty()) { - GraphTargetItem expr = stack.pop(); - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } - output.add(new IfItem(null, expr, new ArrayList(), new ArrayList())); - } - part.nextParts.remove(0); - } - }*/ if (parseNext) { List retCheck = check(code, localData, allParts, stack, parent, part, stopPart, loops, output, currentLoop, staticOperation, path); if (retCheck != null) { @@ -1441,134 +1485,15 @@ public class Graph { currentRet.addAll(output); } } - - /** - * AND / OR detection - */ - if (parseNext && part.nextParts.size() == 2) { - if ((stack.size() >= 2) && (stack.get(stack.size() - 1) instanceof NotItem) && (((NotItem) (stack.get(stack.size() - 1))).getOriginal().getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { - GraphPart sp0 = getNextNoJump(part.nextParts.get(0), localData); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1), localData); - boolean reversed = false; - loopContinues = getLoopsContinues(loops); - loopContinues.add(part);//??? - if (sp1.leadsTo(localData, this, code, sp0, loops)) { - } else if (sp0.leadsTo(localData, this, code, sp1, loops)) { - reversed = true; - } - GraphPart next = reversed ? sp0 : sp1; - GraphTargetItem ti; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - List stopPart2 = new ArrayList<>(stopPart); - GraphPart andOrStopPart = reversed ? sp1 : sp0; - stopPart2.add(andOrStopPart); - GraphTargetItem first = ((NotItem) stack.pop()).getOriginal(); - stack.pop(); - stack.push(new MarkItem("disposable")); - printGraph(visited, localData, stack, allParts, parent, next, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); - GraphTargetItem second = stack.pop(); - - if (!reversed) { - AndItem a = new AndItem(null, first, second); - stack.push(a); - a.firstPart = part; - if (second instanceof AndItem) { - a.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - a.firstPart = ((OrItem) second).firstPart; - } - } else { - OrItem o = new OrItem(null, first, second); - stack.push(o); - o.firstPart = part; - if (second instanceof AndItem) { - o.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - o.firstPart = ((OrItem) second).firstPart; - } - } - next = reversed ? sp1 : sp0; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - currentRet.addAll(printGraph(visited, localData, stack, allParts, parent, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); - } - } - parseNext = false; - //return ret; - } else if ((stack.size() >= 2) && (stack.get(stack.size() - 1).getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { - GraphPart sp0 = getNextNoJump(part.nextParts.get(0), localData); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1), localData); - boolean reversed = false; - loopContinues = getLoopsContinues(loops); - loopContinues.add(part);//??? - if (sp1.leadsTo(localData, this, code, sp0, loops)) { - } else if (sp0.leadsTo(localData, this, code, sp1, loops)) { - reversed = true; - } - GraphPart next = reversed ? sp0 : sp1; - GraphTargetItem ti; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - List stopPart2 = new ArrayList<>(stopPart); - GraphPart andOrStopPart = reversed ? sp1 : sp0; - //andOrStopPart.stopPartType = GraphPart.StopPartType.AND_OR; - stopPart2.add(andOrStopPart); - GraphTargetItem first = stack.pop(); - stack.pop(); - stack.push(new MarkItem("disposable")); - printGraph(visited, localData, stack, allParts, parent, next, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); - //stack = andOrStopPart.andOrStack; // Use stack that was stored upon reaching AND_OR stopPart - GraphTargetItem second = stack.pop(); - //GraphTargetItem first = stack.pop(); - //andOrStopPart.stopPartType = GraphPart.StopPartType.NONE; // Reset stopPartType - - if (reversed) { - AndItem a = new AndItem(null, first, second); - stack.push(a); - a.firstPart = part; - if (second instanceof AndItem) { - a.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - a.firstPart = ((OrItem) second).firstPart; - } - } else { - OrItem o = new OrItem(null, first, second); - stack.push(o); - o.firstPart = part; - if (second instanceof OrItem) { - o.firstPart = ((OrItem) second).firstPart; - } - if (second instanceof AndItem) { - o.firstPart = ((AndItem) second).firstPart; - } - } - - next = reversed ? sp1 : sp0; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - currentRet.addAll(printGraph(visited, localData, stack, allParts, parent, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); - } - } - parseNext = false; - //return ret; - } - } //********************************END PART DECOMPILING - if (parseNext) { if (part.nextParts.size() > 2) {//direct switch, seen in the wild... GraphPart next = getMostCommonPart(localData, part.nextParts, loops); List vis = new ArrayList<>(); GraphTargetItem switchedItem = stack.pop(); + makeAllCommands(currentRet, stack); + List caseValues = new ArrayList<>(); List> caseCommands = new ArrayList<>(); List defaultCommands = new ArrayList<>(); @@ -1604,10 +1529,15 @@ public class Graph { } } if (next != p) { + //int stackLenBefore = stack.size(); + TranslateStack s2 = (TranslateStack) stack.clone(); + s2.clear(); + List nextCommands = printGraph(visited, prepareBranchLocalData(localData), s2, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + makeAllCommands(nextCommands, s2); if (first) { - defaultCommands = printGraph(visited, prepareBranchLocalData(localData), stack, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + defaultCommands = nextCommands; } else { - caseCommands.add(printGraph(visited, prepareBranchLocalData(localData), stack, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1)); + caseCommands.add(nextCommands); } vis.add(p); } @@ -1623,41 +1553,23 @@ public class Graph { GraphPart nextOnePart = null; if (part.nextParts.size() == 2) { GraphTargetItem expr = stack.pop(); - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } - if (staticOperation != SOP_USE_STATIC) { - if (expr.isCompileTime()) { - boolean doJump = EcmaScript.toBoolean(expr.getResult()); - if (doJump) { - nextOnePart = part.nextParts.get(0); - } else { - nextOnePart = part.nextParts.get(1); - } - if (staticOperation == SOP_REMOVE_STATIC) { - //TODO - } - } - } + /*if (expr instanceof LogicalOpItem) { + expr = ((LogicalOpItem) expr).invert(); + } else { + expr = new NotItem(null, expr); + }*/ if (nextOnePart == null) { List nps; - /*nps = new ArrayList<>(part.nextParts); - for(int i=0;i onTrue = new ArrayList<>(); + trueStack.clear(); + falseStack.clear(); + /*int trueStackSizeBefore = trueStack.size(); + int falseStackSizeBefore = falseStack.size(); + */ boolean isEmpty = nps.get(0) == nps.get(1); if (isEmpty) { @@ -1665,59 +1577,63 @@ public class Graph { } List stopPart2 = new ArrayList<>(stopPart); - //GraphPart.CommonPartStack commonPartStack = null; + if ((!isEmpty) && (next != null)) { - /*commonPartStack = next.new CommonPartStack(); - if (next.commonPartStacks == null) { - next.commonPartStacks = new ArrayList<>(); - } - next.stopPartType = GraphPart.StopPartType.COMMONPART; - */ stopPart2.add(next); } + List onTrue = new ArrayList<>(); if (!isEmpty) { onTrue = printGraph(visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); } List onFalse = new ArrayList<>(); if (!isEmpty) { - /*if (next != null) { - commonPartStack.isTrueStack = false; //stopPart must know it needs to store falseStack - }*/ onFalse = printGraph(visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); } + //List out2 = new ArrayList<>(); + //makeAllCommands(out2, stack); + makeAllCommands(onTrue, trueStack); + makeAllCommands(onFalse, falseStack); - /* if there is a stopPart (next), then Graph will be further analyzed starting from the stopPart: - * trueStack and falseStack must be set equal to corresponding stack that was built upon reaching stopPart. - if ((!isEmpty) && (next != null)) { - if ((commonPartStack.trueStack != null) && (commonPartStack.falseStack != null)) { - trueStack = commonPartStack.trueStack; - falseStack = commonPartStack.falseStack; - } - next.commonPartStacks.remove(next.commonPartStacks.size() - 1); - if (next.commonPartStacks.isEmpty()) { - next.stopPartType = GraphPart.StopPartType.NONE; // reset StopPartType - } - }*/ - if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() == trueStackSizeBefore + 1) && (falseStack.size() == falseStackSizeBefore + 1)) { - stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop())); + if (!isEmpty(onTrue) && !isEmpty(onFalse) && onTrue.size() == 1 && onFalse.size() == 1 && (onTrue.get(0) instanceof PushItem) && (onFalse.get(0) instanceof PushItem)) { + stack.push(new TernarOpItem(null, expr.invert(null), ((PushItem) onTrue.get(0)).value, ((PushItem) onFalse.get(0)).value)); } else { - currentRet.add(new IfItem(null, expr, onTrue, onFalse)); - } - if (next != null) { - if (trueStack.size() != trueStackSizeBefore || falseStack.size() != falseStackSizeBefore) { - // it's a hack, because duplicates all instructions in the next part, but better than EmptyStackException - onTrue = printGraph(visited, localData, trueStack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1); - onFalse = printGraph(visited, localData, falseStack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1); - if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() == trueStackSizeBefore + 1) && (falseStack.size() == falseStackSizeBefore + 1)) { - stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop())); + boolean isIf = true; + if (!stack.isEmpty() && onFalse.isEmpty() && onTrue.size() == 2 && (onTrue.get(0) instanceof PopItem) && (onTrue.get(1) instanceof PushItem)) { + GraphTargetItem prevExpr = stack.pop(); + GraphTargetItem leftSide = expr; + + GraphTargetItem rightSide = ((PushItem) onTrue.get(1)).value; + if (leftSide instanceof DuplicateItem) { + isIf = false; + stack.push(new OrItem(null, prevExpr, rightSide)); + } else if (leftSide.invert(null) instanceof DuplicateItem) { + isIf = false; + stack.push(new AndItem(null, prevExpr, rightSide)); + } else if (prevExpr instanceof FalseItem) { + isIf = false; + stack.push(new OrItem(null, leftSide, rightSide)); + } else if (prevExpr instanceof TrueItem) { + isIf = false; + stack.push(new AndItem(null, leftSide, rightSide)); } else { - currentRet.add(new IfItem(null, expr, onTrue, onFalse)); + //:-( } - } else { - printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1); } + + if (isIf) { + makeAllCommands(currentRet, stack); + IfItem b = new IfItem(null, expr.invert(null), onTrue, onFalse); + currentRet.add(b); + if (processSubBlk(b, null)) { + stack.push(new PopItem(null)); + } + } + } + //currentRet.addAll(out2); + if (next != null) { + printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1); //currentRet.addAll(); } } @@ -1751,7 +1667,7 @@ public class Graph { stopContPart.add(currentLoop.loopContinue); GraphPart precoBackup = currentLoop.loopPreContinue; currentLoop.loopPreContinue = null; - loopItem.commands.addAll(printGraph(visited, localData, new TranslateStack(), allParts, null, precoBackup, stopContPart, loops, null, staticOperation, path, recursionLevel + 1)); + loopItem.commands.addAll(printGraph(visited, localData, new TranslateStack(path), allParts, null, precoBackup, stopContPart, loops, null, staticOperation, path, recursionLevel + 1)); } } @@ -1788,7 +1704,7 @@ public class Graph { GraphTargetItem expr = ifi.expression; if (inverted) { if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); + expr = ((LogicalOpItem) expr).invert(null); } else { expr = new NotItem(null, expr); } @@ -1808,7 +1724,7 @@ public class Graph { currentLoop.loopPreContinue = null; List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(currentLoop.loopContinue); - finalComm = printGraph(visited, localData, new TranslateStack(), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + finalComm = printGraph(visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); currentLoop.loopPreContinue = backup; checkContinueAtTheEnd(finalComm, currentLoop); } @@ -1848,11 +1764,7 @@ public class Graph { List exprList = new ArrayList<>(); GraphTargetItem expr = ifi.expression; if (inverted) { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } + expr = expr.invert(null); } checkContinueAtTheEnd(bodyBranch, currentLoop); @@ -1889,7 +1801,7 @@ public class Graph { currentLoop.loopPreContinue = null; List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(currentLoop.loopContinue); - List finalComm = printGraph(visited, localData, new TranslateStack(), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + List finalComm = printGraph(visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); currentLoop.loopPreContinue = backup; checkContinueAtTheEnd(finalComm, currentLoop); @@ -1914,11 +1826,7 @@ public class Graph { List exprList = new ArrayList<>(finalComm); GraphTargetItem expr = ifi.expression; if (invert) { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } + expr = expr.invert(null); } exprList.add(expr); ret.add(index, li = new DoWhileItem(null, currentLoop, loopItem.commands, exprList)); @@ -1943,7 +1851,7 @@ public class Graph { } if (currentLoop.loopBreak != null) { - ret.addAll(printGraph(visited, localData, stack, allParts, part, currentLoop.loopBreak, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); + ret.addAll(printGraph(visited, localData, sPreLoop, allParts, part, currentLoop.loopBreak, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); } } @@ -2157,4 +2065,35 @@ public class Graph { } while (part != null); return ret; } + + protected static void makeAllStack(List commands, TranslateStack stack) { + int pcnt = 0; + for (int i = commands.size() - 1; i >= 0; i--) { + if (commands.get(i) instanceof PushItem) { + pcnt++; + } else { + break; + } + } + for (int i = commands.size() - pcnt; i < commands.size(); i++) { + stack.push(commands.remove(i).value); + i--; + } + } + + protected static void makeAllCommands(List commands, TranslateStack stack) { + int clen = commands.size(); + BreakItem br = null; + if (!commands.isEmpty()) { + if (commands.get(commands.size() - 1) instanceof BreakItem) { + clen--; + } + } + while (stack.size() > 0) { + GraphTargetItem p = stack.pop(); + if (!(p instanceof PopItem)) { + commands.add(clen, new PushItem(p)); + } + } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java index 2e4e823b4..39c25a6a6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java @@ -1,52 +1,52 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.graph; - -import com.jpexs.decompiler.flash.BaseLocalData; -import java.io.Serializable; -import java.util.List; - -/** - * - * @author JPEXS - */ -public interface GraphSourceItem extends Serializable { - - public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException; - - public boolean isJump(); - - public boolean isBranch(); - - public boolean isExit(); - - public long getOffset(); - - public boolean ignoredLoops(); - - public List getBranches(GraphSource code); - - public boolean isIgnored(); - - public void setIgnored(boolean ignored, int pos); - - public boolean isDeobfuscatePop(); - - public int getLine(); - - public String getFile(); -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph; + +import com.jpexs.decompiler.flash.BaseLocalData; +import java.io.Serializable; +import java.util.List; + +/** + * + * @author JPEXS + */ +public interface GraphSourceItem extends Serializable, Cloneable { + + public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException; + + public boolean isJump(); + + public boolean isBranch(); + + public boolean isExit(); + + public long getOffset(); + + public boolean ignoredLoops(); + + public List getBranches(GraphSource code); + + public boolean isIgnored(); + + public void setIgnored(boolean ignored, int pos); + + public boolean isDeobfuscatePop(); + + public int getLine(); + + public String getFile(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index 8ccf9786e..34318ea16 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -1,298 +1,319 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.graph; - -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; -import com.jpexs.decompiler.graph.model.BinaryOp; -import com.jpexs.decompiler.graph.model.LocalData; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * - * @author JPEXS - */ -public abstract class GraphTargetItem implements Serializable { - - public static final int PRECEDENCE_PRIMARY = 0; - - public static final int PRECEDENCE_POSTFIX = 1; - - public static final int PRECEDENCE_UNARY = 2; - - public static final int PRECEDENCE_MULTIPLICATIVE = 3; - - public static final int PRECEDENCE_ADDITIVE = 4; - - public static final int PRECEDENCE_BITWISESHIFT = 5; - - public static final int PRECEDENCE_RELATIONAL = 6; - - public static final int PRECEDENCE_EQUALITY = 7; - - public static final int PRECEDENCE_BITWISEAND = 8; - - public static final int PRECEDENCE_BITWISEXOR = 9; - - public static final int PRECEDENCE_BITWISEOR = 10; - - public static final int PRECEDENCE_LOGICALAND = 11; - - public static final int PRECEDENCE_LOGICALOR = 12; - - public static final int PRECEDENCE_CONDITIONAL = 13; - - public static final int PRECEDENCE_ASSIGMENT = 14; - - public static final int PRECEDENCE_COMMA = 15; - - public static final int NOPRECEDENCE = 16; - - public GraphSourceItem src; - - public int pos = -1; - - protected int precedence; - - public List moreSrc = new ArrayList<>(); - - public GraphPart firstPart; - - public GraphTargetItem value; - - protected HighlightData srcData = new HighlightData(); - - public int getLine() { - if (src != null) { - return src.getLine(); - } - return 0; - } - - public String getFile() { - if (src != null) { - return src.getFile(); - } - return null; - } - - public GraphPart getFirstPart() { - if (value == null) { - return firstPart; - } - GraphPart ret = value.getFirstPart(); - if (ret == null) { - return firstPart; - } - return ret; - } - - public GraphTargetItem() { - this(null, NOPRECEDENCE); - } - - public GraphTargetItem(GraphSourceItem src, int precedence) { - this.src = src; - this.precedence = precedence; - } - - public List getNeededSources() { - List ret = new ArrayList<>(); - ret.add(new GraphSourceItemPos(src, pos)); - ret.addAll(moreSrc); - if (value != null) { - ret.addAll(value.getNeededSources()); - } - return ret; - } - - public GraphTextWriter toStringSemicoloned(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.startOffset(src, pos, srcData); - appendTo(writer, localData); - if (needsSemicolon()) { - writer.appendNoHilight(";"); - } - writer.endOffset(); - return writer; - } - - public boolean needsSemicolon() { - return true; - } - - @Override - public String toString() { - return this.getClass().getName(); - } - - public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.startOffset(src, pos, srcData); - appendTo(writer, localData); - writer.endOffset(); - return writer; - } - - public abstract GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException; - - public String toString(LocalData localData) throws InterruptedException { - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - toString(writer, localData); - return writer.toString(); - } - - public int getPrecedence() { - return precedence; - } - - public boolean isCompileTime() { - Set dependencies = new HashSet<>(); - dependencies.add(this); - return isCompileTime(dependencies); - } - - public boolean isCompileTime(Set dependencies) { - return false; - } - - public boolean hasSideEffect() { - return false; - } - - public boolean isVariableComputed() { - return false; - } - - public Object getResult() { - return null; - } - - public String toStringNoQuotes(LocalData localData) { - return toString(); - } - - public GraphTextWriter toStringNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.startOffset(src, pos, srcData); - appendToNoQuotes(writer, localData); - writer.endOffset(); - return writer; - } - - public GraphTextWriter appendToNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return toString(writer, localData); - } - - public GraphTargetItem getNotCoerced() { - return this; - } - - public GraphTargetItem getThroughRegister() { - return this; - } - - public boolean needsNewLine() { - return false; - } - - public GraphTextWriter toStringNL(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.startOffset(src, pos, srcData); - appendTo(writer, localData); - if (needsNewLine()) { - writer.newLine(); - } - writer.endOffset(); - return writer; - } - - public boolean isEmpty() { - return false; - } - - public GraphTargetItem getThroughNotCompilable() { - return this; - } - - public GraphTargetItem getThroughDuplicate() { - return this; - } - - public boolean valueEquals(GraphTargetItem target) { - return equals(target); - } - - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - return new ArrayList<>(); - } - - public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - if (!hasReturnValue()) { - return toSource(localData, generator); - } - return generator.generateDiscardValue(localData, this); - } - - protected List toSourceBinary(BinaryOp op, GraphSourceItem action) { - List ret = new ArrayList<>(); - - return ret; - } - - public static List toSourceMerge(SourceGeneratorLocalData localData, SourceGenerator gen, Object... tar) throws CompilationException { - List ret = new ArrayList<>(); - for (Object o : tar) { - if (o == null) { - continue; - } - if (o instanceof GraphTargetItem) { - ret.addAll(((GraphTargetItem) o).toSource(localData, gen)); - } - if (o instanceof GraphSourceItem) { - ret.add((GraphSourceItem) o); - } - if (o instanceof List) { - List l = (List) o; - for (Object o2 : l) { - if (o2 instanceof GraphSourceItem) { - ret.add((GraphSourceItem) o2); - } - if (o2 instanceof GraphTargetItem) { - ret.addAll(((GraphTargetItem) o2).toSource(localData, gen)); - } - } - } - } - return ret; - } - - public abstract boolean hasReturnValue(); - - public List getAllSubItems() { - List ret = new ArrayList<>(); - if (value != null) { - ret.add(value); - } - return ret; - } - - public abstract GraphTargetItem returnType(); -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; +import com.jpexs.decompiler.graph.model.BinaryOp; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.decompiler.graph.model.LogicalOpItem; +import com.jpexs.decompiler.graph.model.NotItem; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public abstract class GraphTargetItem implements Serializable, Cloneable { + + public static final int PRECEDENCE_PRIMARY = 0; + + public static final int PRECEDENCE_POSTFIX = 1; + + public static final int PRECEDENCE_UNARY = 2; + + public static final int PRECEDENCE_MULTIPLICATIVE = 3; + + public static final int PRECEDENCE_ADDITIVE = 4; + + public static final int PRECEDENCE_BITWISESHIFT = 5; + + public static final int PRECEDENCE_RELATIONAL = 6; + + public static final int PRECEDENCE_EQUALITY = 7; + + public static final int PRECEDENCE_BITWISEAND = 8; + + public static final int PRECEDENCE_BITWISEXOR = 9; + + public static final int PRECEDENCE_BITWISEOR = 10; + + public static final int PRECEDENCE_LOGICALAND = 11; + + public static final int PRECEDENCE_LOGICALOR = 12; + + public static final int PRECEDENCE_CONDITIONAL = 13; + + public static final int PRECEDENCE_ASSIGMENT = 14; + + public static final int PRECEDENCE_COMMA = 15; + + public static final int NOPRECEDENCE = 16; + + public GraphSourceItem src; + + public int pos = -1; + + protected int precedence; + + public List moreSrc = new ArrayList<>(); + + public GraphPart firstPart; + + public GraphTargetItem value; + + protected HighlightData srcData = new HighlightData(); + + public int getLine() { + if (src != null) { + return src.getLine(); + } + return 0; + } + + public String getFile() { + if (src != null) { + return src.getFile(); + } + return null; + } + + public GraphPart getFirstPart() { + if (value == null) { + return firstPart; + } + GraphPart ret = value.getFirstPart(); + if (ret == null) { + return firstPart; + } + return ret; + } + + public GraphTargetItem() { + this(null, NOPRECEDENCE); + } + + public GraphTargetItem(GraphSourceItem src, int precedence) { + this.src = src; + this.precedence = precedence; + } + + public List getNeededSources() { + List ret = new ArrayList<>(); + ret.add(new GraphSourceItemPos(src, pos)); + ret.addAll(moreSrc); + if (value != null) { + ret.addAll(value.getNeededSources()); + } + return ret; + } + + public GraphTextWriter toStringSemicoloned(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startOffset(src, pos, srcData); + appendTo(writer, localData); + if (needsSemicolon()) { + writer.appendNoHilight(";"); + } + writer.endOffset(); + return writer; + } + + public boolean needsSemicolon() { + return true; + } + + @Override + public String toString() { + return this.getClass().getName(); + } + + public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startOffset(src, pos, srcData); + appendTo(writer, localData); + writer.endOffset(); + return writer; + } + + public abstract GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException; + + public String toString(LocalData localData) throws InterruptedException { + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); + toString(writer, localData); + return writer.toString(); + } + + public int getPrecedence() { + return precedence; + } + + public boolean isCompileTime() { + Set dependencies = new HashSet<>(); + dependencies.add(this); + return isCompileTime(dependencies); + } + + public boolean isCompileTime(Set dependencies) { + return false; + } + + public boolean hasSideEffect() { + return false; + } + + public boolean isVariableComputed() { + return false; + } + + public Object getResult() { + return null; + } + + public String toStringNoQuotes(LocalData localData) { + return toString(); + } + + public GraphTextWriter toStringNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startOffset(src, pos, srcData); + appendToNoQuotes(writer, localData); + writer.endOffset(); + return writer; + } + + public GraphTextWriter appendToNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { + return toString(writer, localData); + } + + public GraphTargetItem getNotCoerced() { + return this; + } + + public GraphTargetItem getThroughRegister() { + return this; + } + + public boolean needsNewLine() { + return false; + } + + public GraphTextWriter toStringNL(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startOffset(src, pos, srcData); + appendTo(writer, localData); + if (needsNewLine()) { + writer.newLine(); + } + writer.endOffset(); + return writer; + } + + public boolean isEmpty() { + return false; + } + + public GraphTargetItem getThroughNotCompilable() { + return this; + } + + public GraphTargetItem getThroughDuplicate() { + return this; + } + + public boolean valueEquals(GraphTargetItem target) { + return equals(target); + } + + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return new ArrayList<>(); + } + + public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + if (!hasReturnValue()) { + return toSource(localData, generator); + } + return generator.generateDiscardValue(localData, this); + } + + protected List toSourceBinary(BinaryOp op, GraphSourceItem action) { + List ret = new ArrayList<>(); + + return ret; + } + + public static List toSourceMerge(SourceGeneratorLocalData localData, SourceGenerator gen, Object... tar) throws CompilationException { + List ret = new ArrayList<>(); + for (Object o : tar) { + if (o == null) { + continue; + } + if (o instanceof GraphTargetItem) { + ret.addAll(((GraphTargetItem) o).toSource(localData, gen)); + } + if (o instanceof GraphSourceItem) { + ret.add((GraphSourceItem) o); + } + if (o instanceof List) { + List l = (List) o; + for (Object o2 : l) { + if (o2 instanceof GraphSourceItem) { + ret.add((GraphSourceItem) o2); + } + if (o2 instanceof GraphTargetItem) { + ret.addAll(((GraphTargetItem) o2).toSource(localData, gen)); + } + } + } + } + return ret; + } + + public abstract boolean hasReturnValue(); + + public List getAllSubItems() { + List ret = new ArrayList<>(); + if (value != null) { + ret.add(value); + } + return ret; + } + + public abstract GraphTargetItem returnType(); + + @Override + protected GraphTargetItem clone() { + try { + return (GraphTargetItem) super.clone(); + } catch (CloneNotSupportedException ex) { + return null; + } + } + + /*public GraphTargetItem invert() { + return invert(null); + }*/ + public GraphTargetItem invert(GraphSourceItem src) { + return new NotItem(src, this); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java new file mode 100644 index 000000000..e9bd81880 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java @@ -0,0 +1,10 @@ +package com.jpexs.decompiler.graph; + +/** + * + * @author JPEXS + */ +public interface SimpleValue { + + public boolean isSimpleValue(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java index 7c1694d78..0eb8d34b3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -22,12 +23,14 @@ import com.jpexs.decompiler.graph.model.CommaExpressionItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.DoWhileItem; import com.jpexs.decompiler.graph.model.DuplicateItem; +import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.ForItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; +import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.decompiler.graph.model.WhileItem; import java.util.List; @@ -37,6 +40,10 @@ import java.util.List; */ public interface SourceGenerator { + public List generate(SourceGeneratorLocalData localData, TrueItem item) throws CompilationException; + + public List generate(SourceGeneratorLocalData localData, FalseItem item) throws CompilationException; + public List generate(SourceGeneratorLocalData localData, AndItem item) throws CompilationException; public List generate(SourceGeneratorLocalData localData, OrItem item) throws CompilationException; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java index 647519182..cc68f15ea 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java @@ -16,11 +16,51 @@ */ package com.jpexs.decompiler.graph; +import com.jpexs.decompiler.graph.model.PopItem; import java.util.Stack; +import java.util.logging.Level; +import java.util.logging.Logger; /** * * @author JPEXS */ public class TranslateStack extends Stack { + + private static PopItem pop = new PopItem(null); + + private String path; + + public TranslateStack(String path) { + this.path = path; + } + + public String getPath() { + return path; + } + + @Override + public synchronized GraphTargetItem peek() { + if (path != null) { + if (this.isEmpty()) { + Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attemp to Peek empty stack", path); + return pop; + } + } + return super.peek(); + } + + @Override + public synchronized GraphTargetItem pop() { + if (path != null) { + if (this.isEmpty()) { + PopItem oldpop = pop; + pop = new PopItem(null); + Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attemp to Pop empty stack", path); + return oldpop; + } + } + return super.pop(); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java index c1f8f8f87..3e655bdf3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -20,6 +21,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import java.util.List; @@ -29,7 +31,7 @@ import java.util.Set; * * @author JPEXS */ -public class DuplicateItem extends GraphTargetItem { +public class DuplicateItem extends GraphTargetItem implements SimpleValue { public DuplicateItem(GraphSourceItem src, GraphTargetItem value) { super(src, value.getPrecedence()); @@ -43,7 +45,12 @@ public class DuplicateItem extends GraphTargetItem { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return value.toString(writer, localData); + if ((value instanceof SimpleValue) && (((SimpleValue) value).isSimpleValue())) { + return value.appendTo(writer, localData); + } + writer.append("§§dup("); + value.appendTo(writer, localData); + return writer.append(")"); } @Override @@ -89,4 +96,14 @@ public class DuplicateItem extends GraphTargetItem { public GraphTargetItem returnType() { return TypeItem.UNBOUNDED; } + + /*@Override + public GraphTargetItem invert(GraphSourceItem src) { + return //new DuplicateItem(src, value instanceof NotItem ? (value.value) : new NotItem(src, value)); + }*/ + @Override + public boolean isSimpleValue() { + return ((value instanceof SimpleValue) && ((SimpleValue) value).isSimpleValue()); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ExitItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ExitItem.java index b02e93c69..b1a6fefe6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ExitItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ExitItem.java @@ -1,18 +1,19 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java new file mode 100644 index 000000000..f9704f06f --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. */ +package com.jpexs.decompiler.graph.model; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.TypeItem; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class FalseItem extends GraphTargetItem implements LogicalOpItem, SimpleValue { + + public FalseItem(GraphSourceItem src) { + super(src, PRECEDENCE_PRIMARY); + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) { + return writer.append("false"); + } + + @Override + public boolean hasReturnValue() { + return true; + } + + @Override + public GraphTargetItem returnType() { + return TypeItem.BOOLEAN; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return generator.generate(localData, this); + } + + @Override + public GraphTargetItem invert(GraphSourceItem neqSrc) { + return new TrueItem(null); + } + + @Override + public boolean isSimpleValue() { + return true; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java index c3bd312ca..43f9f7caf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java @@ -75,11 +75,7 @@ public class IfItem extends GraphTargetItem implements Block { expr = ((NotItem) expr).getOriginal(); } } else { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } + expr = expr.invert(null); ifBranch = onFalse; elseBranch = onTrue; } @@ -112,7 +108,10 @@ public class IfItem extends GraphTargetItem implements Block { } for (GraphTargetItem ti : elseBranch) { if (!ti.isEmpty()) { - ti.toStringSemicoloned(writer, localData).newLine(); + ti.toStringSemicoloned(writer, localData); + if (!elseIf) { + writer.newLine(); + } } } if (!elseIf) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LogicalOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LogicalOpItem.java index 3cfd1eaad..de055b908 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LogicalOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LogicalOpItem.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; +import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; /** @@ -23,5 +25,5 @@ import com.jpexs.decompiler.graph.GraphTargetItem; */ public interface LogicalOpItem { - public GraphTargetItem invert(); + public GraphTargetItem invert(GraphSourceItem src); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java index a7369764f..5becbe13e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -57,11 +58,6 @@ public class NotItem extends UnaryOpItem implements LogicalOpItem, Inverted { return value.isCompileTime(dependencies); } - @Override - public GraphTargetItem invert() { - return value; - } - public GraphTargetItem getOriginal() { return value; } @@ -80,4 +76,10 @@ public class NotItem extends UnaryOpItem implements LogicalOpItem, Inverted { public GraphTargetItem returnType() { return TypeItem.BOOLEAN; } + + @Override + public GraphTargetItem invert(GraphSourceItem src) { + return value; + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PopItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PopItem.java new file mode 100644 index 000000000..68ed404f5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PopItem.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph.model; + +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TypeItem; + +/** + * + * @author JPEXS + */ +public class PopItem extends GraphTargetItem { + + public PopItem(GraphSourceItem src) { + super(src, PRECEDENCE_PRIMARY); + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + //Logger.getLogger(PopItem.class.getName()).log(Level.WARNING, "Pop item left in the source code"); + writer.append("§§pop()"); + return writer; + } + + @Override + public boolean hasReturnValue() { + return true; + } + + @Override + public GraphTargetItem returnType() { + return TypeItem.UNBOUNDED; + } + + @Override + public Object getResult() { + return new Null(); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PushItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PushItem.java new file mode 100644 index 000000000..a26566786 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/PushItem.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph.model; + +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.GraphTargetItem; + +/** + * + * @author JPEXS + */ +public class PushItem extends GraphTargetItem { + + public PushItem(GraphTargetItem val) { + super(val.src, val.getPrecedence()); + this.value = val; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + //Logger.getLogger(PushItem.class.getName()).log(Level.WARNING, "Push item left in the source code"); + writer.append("§§push("); + value.appendTo(writer, localData); + writer.append(")"); + return writer; + } + + @Override + public boolean hasReturnValue() { + return true; + } + + @Override + public GraphTargetItem returnType() { + return value.returnType(); + } + + @Override + public GraphTargetItem getNotCoerced() { + return value.getNotCoerced(); + } + + @Override + public GraphTargetItem getThroughDuplicate() { + return value.getThroughDuplicate(); + } + + @Override + public GraphTargetItem getThroughRegister() { + return value.getThroughRegister(); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java index 07ebbbd62..99069a463 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java @@ -1,30 +1,36 @@ /* * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; +import java.util.List; /** * * @author JPEXS */ -public class TrueItem extends GraphTargetItem { +public class TrueItem extends GraphTargetItem implements LogicalOpItem, SimpleValue { public TrueItem(GraphSourceItem src) { super(src, PRECEDENCE_PRIMARY); @@ -44,4 +50,19 @@ public class TrueItem extends GraphTargetItem { public GraphTargetItem returnType() { return TypeItem.BOOLEAN; } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return generator.generate(localData, this); + } + + @Override + public GraphTargetItem invert(GraphSourceItem neqSrc) { + return new FalseItem(null); + } + + @Override + public boolean isSimpleValue() { + return true; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java index 9c4d3f434..d9fa93719 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java @@ -25,8 +25,6 @@ import java.util.Set; public abstract class UnaryOpItem extends GraphTargetItem implements UnaryOp { - public GraphTargetItem value; - public String operator; public UnaryOpItem(GraphSourceItem instruction, int precedence, GraphTargetItem value, String operator) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java index 2d4d117ff..afe5c4f7b 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java @@ -1,806 +1,807 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.helpers.CodeFormatting; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.tags.DoActionTag; -import com.jpexs.decompiler.flash.tags.ShowFrameTag; -import com.jpexs.decompiler.flash.tags.Tag; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -/** - * - * @author JPEXS - */ -public class ActionScript2Test extends ActionStript2TestBase { - - @BeforeClass - public void init() throws IOException, InterruptedException { - //Main.initLogging(false); - Configuration.autoDeobfuscate.set(false); - Configuration.decompile.set(true); - Configuration.registerNameFormat.set("_loc%d_"); - swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false); - } - - private void compareSrc(int frame, String expectedResult) { - DoActionTag doa = getFrameSource(frame); - assertNotNull(doa); - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - try { - Action.actionsToSource(doa, doa.getActions(), "", writer); - } catch (InterruptedException ex) { - fail(); - } - String actualResult = cleanPCode(writer.toString()); - expectedResult = cleanPCode(expectedResult); - assertEquals(actualResult, expectedResult); - - } - - private DoActionTag getFrameSource(int frame) { - int f = 0; - DoActionTag lastDoa = null; - - for (Tag t : swf.tags) { - if (t instanceof DoActionTag) { - lastDoa = (DoActionTag) t; - } - if (t instanceof ShowFrameTag) { - f++; - if (f == frame) { - return lastDoa; - } - lastDoa = null; - } - } - return null; - } - - @Test - public void frame23_Test() { - compareSrc(23, "stop();\r\n" - ); - } - - @Test - public void frame24_unicodeTest() { - compareSrc(24, "trace(\"unicodeTest\");\r\n" - + "var k = \"\u05d4\u05d9\u05e4\u05d5\u05e4\u05d5\u05d8\u05de\u05d9, \u05d0\u05d5 \u05d0\";\r\n" - + "trace(k);\r\n" - ); - } - - @Test - public void frame25_ifWithElseTest() { - compareSrc(25, "trace(\"ifWithElseTest\");\r\n" - + "var i = 5;\r\n" - + "if(i == 258)\r\n" - + "{\r\n" - + "trace(\"onTrue\");\r\n" - + "}\r\n" - + "else\r\n" - + "{\r\n" - + "trace(\"onFalse\" + i);\r\n" - + "}\r\n" - ); - } - - @Test - public void frame26_forTest() { - compareSrc(26, "trace(\"forTest\");\r\n" - + "var i = 0;\r\n" - + "while(i < 10)\r\n" - + "{\r\n" - + "trace(\"hello:\" + i);\r\n" - + "i++;\r\n" - + "}\r\n" - ); - } - - @Test - public void frame27_whileTest() { - compareSrc(27, "trace(\"whileTest\");\r\n" - + "var i = 0;\r\n" - + "while(i < 10)\r\n" - + "{\r\n" - + "trace(\"hello:\" + i);\r\n" - + "i++;\r\n" - + "}\r\n" - ); - } - - @Test - public void frame28_forWithContinueTest() { - compareSrc(28, "trace(\"forWithContinueTest\");\r\n" - + "var i = 0;\r\n" - + "for(; i < 10; i++)\r\n" - + "{\r\n" - + "trace(\"hello:\" + i);\r\n" - + "if(i == 5)\r\n" - + "{\r\n" - + "trace(\"i==5\");\r\n" - + "if(i == 7)\r\n" - + "{\r\n" - + "continue;\r\n" - + "}\r\n" - + "trace(\"hawk\");\r\n" - + "}\r\n" - + "trace(\"end of the loop\");\r\n" - + "}\r\n" - ); - } - - @Test - public void frame29_doWhileTest() { - compareSrc(29, "trace(\"doWhileTest\");\r\n" - + "var i = 0;\r\n" - + "do\r\n" - + "{\r\n" - + "trace(\"i=\" + i);\r\n" - + "i++;\r\n" - + "}\r\n" - + "while(i < 10);\r\n" - + "trace(\"end\");\r\n" - ); - } - - @Test - public void frame30_switchTest() { - compareSrc(30, "trace(\"switchTest\");\r\n" - + "var i = 5;\r\n" - + "switch(i)\r\n" - + "{\r\n" - + "case 0:\r\n" - + "case 1:\r\n" - + "trace(\"one\");\r\n" - + "break;\r\n" - + "case 2:\r\n" - + "trace(\"two\");\r\n" - + "case 3:\r\n" - + "trace(\"three\");\r\n" - + "break;\r\n" - + "case 4:\r\n" - + "trace(\"four\");\r\n" - + "break;\r\n" - + "default:\r\n" - + "trace(\"default clause\");\r\n" - + "}\r\n" - + "trace(\"scriptend\");\r\n" - ); - } - - @Test - public void frame31_strictEqualsTest() { - compareSrc(31, "trace(\"strictEqualsTest\");\r\n" - + "var i = 5;\r\n" - + "if(i === 5)\r\n" - + "{\r\n" - + "trace(\"equals strict\");\r\n" - + "}\r\n" - + "if(!(i === 5))\r\n" - + "{\r\n" - + "trace(\"not equals strict\");\r\n" - + "}\r\n" - ); - } - - @Test - public void frame32_switchForTest() { - compareSrc(32, "trace(\"switchForTest\");\r\n" - + "var i = 0;\r\n" - + "for(; i < 10; i++)\r\n" - + "{\r\n" - + "switch(i)\r\n" - + "{\r\n" - + "case 0:\r\n" - + "trace(\"zero\");\r\n" - + "continue;\r\n" - + "case 5:\r\n" - + "trace(\"five\");\r\n" - + "break;\r\n" - + "case 10:\r\n" - + "trace(\"ten\");\r\n" - + "break;\r\n" - + "case 1:\r\n" - + "if(i == 7)\r\n" - + "{\r\n" - + "continue;\r\n" - + "}\r\n" - + "trace(\"one\");\r\n" - + "default:\r\n" - + "trace(\"def\");\r\n" - + "}\r\n" - + "trace(\"before loop end\");\r\n" - + "}\r\n" - ); - } - - @Test - public void frame33_functionTest() { - compareSrc(33, "function hello(what, second)\r\n" - + "{\r\n" - + "trace(\"hello \" + what + \"! \" + second);\r\n" - + "}\r\n" - + "trace(\"functionTest\");\r\n" - + "hello(\"friend\",7);\r\n" - ); - } - - @Test - public void frame34_multipleConditionsTest() { - compareSrc(34, "trace(\"multipleConditionsTest\");\r\n" - + "var k = 5;\r\n" - + "if(k == 7 && k == 8)\r\n" - + "{\r\n" - + "trace(\"first\");\r\n" - + "}\r\n" - + "if(k == 9)\r\n" - + "{\r\n" - + "trace(\"second\");\r\n" - + "}\r\n" - + "trace(\"finish\");\r\n" - ); - } - - @Test - public void frame35_multipleConditions2Test() { - compareSrc(35, "trace(\"multipleConditions2Test\");\r\n" - + "var k = 5;\r\n" - + "if(k == 7 && k == 8)\r\n" - + "{\r\n" - + "trace(\"first\");\r\n" - + "}\r\n" - + "if(k == 9 || k == 6)\r\n" - + "{\r\n" - + "trace(\"second\");\r\n" - + "}\r\n" - + "trace(\"finish\");\r\n" - ); - } - - @Test - public void frame36_chainedAssignmentsTest() { - compareSrc(36, "trace(\"chainedAssignmentsTest\");\r\n" - + "var a = 7;\r\n" - + "var b = 8;\r\n" - + "var c = 9;\r\n" - + "var d = c = b = a = 10;\r\n" - + "trace(d);\r\n" - ); - } - - @Test - public void frame37_objectsTest() { - compareSrc(37, "trace(\"objectsTest\");\r\n" - + "var flashBox = new Box(box1);\r\n" - + "_root.onEnterFrame = function()\r\n" - + "{\r\n" - + "flashBox.moveUp();\r\n" - + "};\r\n" - + "var ship = new Ship(200);\r\n" - + "var enemy = new Enemy(56);\r\n" - + "ship.moveDown(0.5);\r\n" - + "ship.moveUp(0.2);\r\n" - + "enemy.moveRight(230);\r\n" - + "enemy.moveLeft(100);\r\n" - + "var mt = new com.jpexs.MyTest();\r\n" - + "mt.test();\r\n" - + "var c = new Cox(box1);\r\n" - ); - } - - @Test - public void frame38_doWhile2Test() { - compareSrc(38, "trace(\"doWhile2Test\");\r\n" - + "var k = 5;\r\n" - + "do\r\n" - + "{\r\n" - + "k++;\r\n" - + "if(k == 7)\r\n" - + "{\r\n" - + "k = 5 * k;\r\n" - + "}\r\n" - + "else\r\n" - + "{\r\n" - + "k = 5 + k;\r\n" - + "}\r\n" - + "}\r\n" - + "while(k < 9);\r\n" - ); - } - - @Test - public void frame39_whileAndTest() { - compareSrc(39, "trace(\"whileAndTest\");\r\n" - + "var a = 5;\r\n" - + "var b = 10;\r\n" - + "while(a < 10 && b > 1)\r\n" - + "{\r\n" - + "a++;\r\n" - + "b--;\r\n" - + "}\r\n" - + "a = 7;\r\n" - + "b = 9;\r\n" - ); - } - - @Test - public void frame40_forInTest() { - compareSrc(40, "function testForIn()\r\n" - + "{\r\n" - + "var _loc1_ = [];\r\n" - + "for(var _loc2_ in _loc1_)\r\n" - + "{\r\n" - + "if(_loc2_ > 3)\r\n" - + "{\r\n" - + "if(_loc2_ == 5)\r\n" - + "{\r\n" - + "return 7;\r\n" - + "}\r\n" - + "return 8;\r\n" - + "}\r\n" - + "}\r\n" - + "}\r\n" - + "trace(\"forInTest\");\r\n" - + "trace(testForIn());\r\n" - + "var arr = [];\r\n" - + "for(var a in arr)\r\n" - + "{\r\n" - + "trace(a);\r\n" - + "}\r\n" - ); - } - - @Test - public void frame41_tryTest() { - compareSrc(41, "trace(\"tryTest\");\r\n" - + "var k = 5;\r\n" - + "try\r\n" - + "{\r\n" - + "k = Infinity;\r\n" - + "}\r\n" - + "catch(e)\r\n" - + "{\r\n" - + "trace(\"bug \" + e);\r\n" - + "}\r\n" - + "finally\r\n" - + "{\r\n" - + "trace(\"huu\");\r\n" - + "}\r\n" - + "trace(\"next\");\r\n" - + "try\r\n" - + "{\r\n" - + "k = 6;\r\n" - + "}\r\n" - + "catch(e)\r\n" - + "{\r\n" - + "trace(\"bug2 \" + e);\r\n" - + "}\r\n" - + "trace(\"next2\");\r\n" - + "var k = 5;\r\n" - + "try\r\n" - + "{\r\n" - + "k = Infinity;\r\n" - + "}\r\n" - + "finally\r\n" - + "{\r\n" - + "trace(\"final\");\r\n" - + "}\r\n" - + "trace(\"end\");\r\n" - ); - } - - @Test - public void frame42_indicesTest() { - compareSrc(42, "trace(\"indicesTest\");\r\n" - + "var k = [1,2,3];\r\n" - + "var b = k[1];\r\n" - + "trace(b);\r\n" - ); - } - - @Test - public void frame43_incDecTest() { - compareSrc(43, "function tst()\r\n" - + "{\r\n" - + "return 1;\r\n" - + "}\r\n" - + "trace(\"incDecTest\");\r\n" - + "var i = 5;\r\n" - + "var b = i++;\r\n" - + "var c = --i + 5;\r\n" - + "trace(\"a:\" + a + \" b:\" + b + \" c:\" + c);\r\n" - + "var arr = [1,2,3];\r\n" - + "arr[tst()]++;\r\n" - + "var d = arr[tst()];\r\n" - + "trace(d);\r\n" - ); - } - - @Test - public void frame44_chainedAssignments2Test() { - compareSrc(44, "trace(\"chainedAssignments2Test\");\r\n" - + "var a = 5;\r\n" - + "var b = 6;\r\n" - + "var c = 7;\r\n" - + "var d = c = b = a = 4;\r\n" - + "if((d = c = b = a = 7) > 2)\r\n" - + "{\r\n" - + "trace(d);\r\n" - + "}\r\n" - + "trace(d + 1);\r\n" - + "var i = 0;\r\n" - + "while(i < 5)\r\n" - + "{\r\n" - + "if(i == 7)\r\n" - + "{\r\n" - + "}\r\n" - + "i++;\r\n" - + "}\r\n" - ); - } - - @Test - public void frame45_function2Test() { - compareSrc(45, "function a()\r\n" - + "{\r\n" - + "trace(\"hi\");\r\n" - + "var _loc1_ = 5;\r\n" - + "if(_loc1_ == 7)\r\n" - + "{\r\n" - + "return undefined;\r\n" - + "}\r\n" - + "_loc1_ = _loc1_ * 9;\r\n" - + "trace(_loc1_);\r\n" - + "}\r\n" - + "trace(\"function2Test\");\r\n" - ); - } - - @Test - public void frame46_tryFunctionTest() { - compareSrc(46, "function testtry()\r\n" - + "{\r\n" - + "var _loc1_ = 5;\r\n" - + "try\r\n" - + "{\r\n" - + "if(_loc1_ == 3)\r\n" - + "{\r\n" - + "return undefined;\r\n" - + "}\r\n" - + "if(_loc1_ == 4)\r\n" - + "{\r\n" - + "throw new Error();\r\n" - + "}\r\n" - + "else\r\n" - + "{\r\n" - + "_loc1_ = 7;\r\n" - + "}\r\n" - + "}\r\n" - + "catch(e)\r\n" - + "{\r\n" - + "trace(\"error\");\r\n" - + "}\r\n" - + "finally\r\n" - + "{\r\n" - + "trace(\"finally\");\r\n" - + "}\r\n" - + "}\r\n" - + "trace(\"tryFunctionTest\");\r\n" - ); - } - - @Test - public void frame47_ternarTest() { - compareSrc(47, "trace(\"ternarTest\");\r\n" - + "var a = 5;\r\n" - + "var b = a != 4?3:2;\r\n" - + "trace(b);\r\n" - ); - } - - @Test - public void frame48_forInInTest() { - compareSrc(48, "function tst()\r\n" - + "{\r\n" - + "var _loc2_ = [];\r\n" - + "_loc2_[0] = [];\r\n" - + "for(var _loc3_ in _loc2_)\r\n" - + "{\r\n" - + "for(var _loc1_ in _loc3_)\r\n" - + "{\r\n" - + "if(_loc1_ == 5)\r\n" - + "{\r\n" - + "return 5;\r\n" - + "}\r\n" - + "}\r\n" - + "if(_loc3_ == 8)\r\n" - + "{\r\n" - + "return 3;\r\n" - + "}\r\n" - + "}\r\n" - + "return 8;\r\n" - + "}\r\n" - + "trace(\"forInInTest\");\r\n" - + "tst();\r\n" - ); - } - - @Test - public void frame49_registersFuncTest() { - compareSrc(49, "function tst(px)\r\n" - + "{\r\n" - + "var _loc1_ = 57;\r\n" - + "_loc1_ = _loc1_ * 27;\r\n" - + "}\r\n" - + "trace(\"registersFuncTest\");\r\n" - + "tst(5);\r\n" - + "var s = String(5);\r\n" - ); - } - - @Test - public void frame50_ifFrameLoadedTest() { - compareSrc(50, "trace(\"ifFrameLoadedTest\");\r\n" - + "ifFrameLoaded(9)\r\n" - + "{\r\n" - + "trace(\"loaded\");\r\n" - + "}\r\n" - ); - } - - @Test - public void frame51_function3Test() { - compareSrc(51, "function tst()\r\n" - + "{\r\n" - + "var _loc1_ = 5;\r\n" - + "c = _loc1_ = 8;\r\n" - + "trace(\"hi\");\r\n" - + "trace(_loc1_);\r\n" - + "if((e = d = f = c = 9) > 5)\r\n" - + "{\r\n" - + "trace(\"dd\");\r\n" - + "}\r\n" - + "}\r\n" - + "trace(\"function3Test\");\r\n" - + "var c = 7;\r\n" - + "var d = 7;\r\n" - + "var e = 8;\r\n" - + "tst();\r\n" - ); - } - - @Test - public void frame52_commaOperatorTest() { - compareSrc(52, "trace(\"commaOperatorTest\");\r\n" - + "var a = 0;\r\n" - + "var b = 0;\r\n" - + "var c = 0;\r\n" - + "while(true)\r\n" - + "{\r\n" - + "a++;\r\n" - + "b = b + 2;\r\n" - + "if(c < 10)\r\n" - + "{\r\n" - + "trace(c);\r\n" - + "c++;\r\n" - + "continue;\r\n" - + "}\r\n" - + "break;\r\n" - + "}\r\n" - + "trace(\"konec\");\r\n" - ); - } - - @Test - public void frame53_commaOperator2Test() { - compareSrc(53, "trace(\"commaOperator2Test\");\r\n" - + "var k = 8;\r\n" - + "do\r\n" - + "{\r\n" - + "if(k == 9)\r\n" - + "{\r\n" - + "trace(\"h\");\r\n" - + "if(k == 9)\r\n" - + "{\r\n" - + "trace(\"f\");\r\n" - + "continue;\r\n" - + "}\r\n" - + "trace(\"b\");\r\n" - + "}\r\n" - + "trace(\"gg\");\r\n" - + "}\r\n" - + "while(k++, k < 10);\r\n" - + "trace(\"ss\");\r\n" - ); - } - - @Test - public void frame54_function4Test() { - compareSrc(54, "function tst()\r\n" - + "{\r\n" - + "var _loc1_ = 5;\r\n" - + "while(_loc1_ < 10)\r\n" - + "{\r\n" - + "if(_loc1_ == 5)\r\n" - + "{\r\n" - + "if(_loc1_ == 6)\r\n" - + "{\r\n" - + "return true;\r\n" - + "}\r\n" - + "_loc1_ = _loc1_ + 1;\r\n" - + "continue;\r\n" - + "}\r\n" - + "return false;\r\n" - + "}\r\n" - + "}\r\n" - + "trace(\"function4Test\");\r\n" - + "tst();\r\n" - ); - } - - @Test - public void frame55_pushTest() { - compareSrc(55, "trace(\"pushTest\");\r\n" - ); - } - - @Test - public void frame56_commaOperator3Test() { - compareSrc(56, "trace(\"commaOperator3Test\");\r\n" - + "var k = 1;\r\n" - + "while(true)\r\n" - + "{\r\n" - + "k++;\r\n" - + "if(k < 10)\r\n" - + "{\r\n" - + "k = k * 5;\r\n" - + "trace(k);\r\n" - + "continue;\r\n" - + "}\r\n" - + "break;\r\n" - + "}\r\n" - + "trace(\"end\");\r\n" - ); - } - - @Test - public void frame57_commaOperator4Test() { - compareSrc(57, "trace(\"commaOperator4Test\");\r\n" - + "var k = 0;\r\n" - + "do\r\n" - + "{\r\n" - + "trace(k);\r\n" - + "if(k == 8)\r\n" - + "{\r\n" - + "trace(\"a\");\r\n" - + "if(k == 9)\r\n" - + "{\r\n" - + "continue;\r\n" - + "}\r\n" - + "trace(\"d\");\r\n" - + "trace(\"b\");\r\n" - + "}\r\n" - + "k++;\r\n" - + "}\r\n" - + "while(k = k + 5, k < 20);\r\n" - + "trace(\"end\");\r\n" - ); - } - - @Test - public void frame58_globalFunctionsTest() { - compareSrc(58, "function tst(p1)\r\n" - + "{\r\n" - + "trace(\"test\");\r\n" - + "}\r\n" - + "trace(\"globalFunctionsTest\");\r\n" - + "var k = Array(1,2,3);\r\n" - + "var a = 1;\r\n" - + "var b = Boolean(a);\r\n" - + "call(5);\r\n" - + "var c = \"A\";\r\n" - + "clearInterval(5);\r\n" - + "clearTimeout(4);\r\n" - + "var mc;\r\n" - + "duplicateMovieClip(mc,\"copy\",16389);\r\n" - + "a = escape(\"how\");\r\n" - + "var f = a;\r\n" - + "fscommand(\"alert(\\\"hi\\\");\");\r\n" - + "a = mc._alpha;\r\n" - + "a = getTimer();\r\n" - + "getURL(\"http://localhost/\",\"wnd\",\"POST\");\r\n" - + "a = getVersion();\r\n" - + "gotoAndPlay(5);\r\n" - + "gotoAndStop(8);\r\n" - + "ifFrameLoaded(4)\r\n" - + "{\r\n" - + "trace(\"loaded\");\r\n" - + "}\r\n" - + "a = int(f);\r\n" - + "a = isFinite(f);\r\n" - + "a = isNaN(f);\r\n" - + "a = length(f);\r\n" - + "loadMovie(\"http://localhost/test.swf\",a,\"GET\");\r\n" - + "loadMovieNum(\"http://localhost/test.swf\",5,\"GET\");\r\n" - + "loadVariables(\"http://localhost/vars.txt\",a,\"GET\");\r\n" - + "loadVariablesNum(\"http://localhost/vars.txt\",4,\"GET\");\r\n" - + "a = mbchr(f);\r\n" - + "a = mblength(f);\r\n" - + "a = mbord(f);\r\n" - + "a = mbsubstring(\"aaaa\",5,4);\r\n" - + "MMExecute(\"destroyPC\");\r\n" - + "nextFrame();\r\n" - + "gotoAndStop(1);\r\n" - + "a = Number(f);\r\n" - + "a = Object(f);\r\n" - + "a = ord(f);\r\n" - + "a = parseFloat(f);\r\n" - + "a = parseInt(f,16);\r\n" - + "play();\r\n" - + "prevFrame();\r\n" - + "gotoAndStop(1);\r\n" - + "print(mc,\"bframe\");\r\n" - + "printAsBitmap(mc,\"bframe\");\r\n" - + "printAsBitmapNum(5,\"bframe\");\r\n" - + "printNum(4,\"bframe\");\r\n" - + "a = random(10);\r\n" - + "removeMovieClip(mc);\r\n" - + "setInterval(tst,5,f);\r\n" - + "mc._alpha = 25;\r\n" - + "setTimeout(tst,5,f);\r\n" - + "showRedrawRegions(false,0);\r\n" - + "startDrag(mc,1,5,5,6,6);\r\n" - + "stop();\r\n" - + "stopAllSounds();\r\n" - + "stopDrag();\r\n" - + "a = String(f);\r\n" - + "a = \"aa\";\r\n" - + "targetPath(f);\r\n" - + "tellTarget(mc)\r\n" - + "{\r\n" - + "trace(\"told\");\r\n" - + "}\r\n" - + "toggleHighQuality();\r\n" - + "a = unescape(f);\r\n" - + "unloadMovie(mc);\r\n" - + "unloadMovieNum(4);\r\n" - + "updateAfterEvent();\r\n" - ); - } - - @Test - public void frame59_unaryOpTest() { - compareSrc(59, "trace(\"unaryOpTest\");\r\n" - + "var a = 5;\r\n" - + "var c = ~a;\r\n" - + "var d = ~(a + c);\r\n" - + "var e = - c;\r\n" - ); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.tags.ShowFrameTag; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript2Test extends ActionStript2TestBase { + + @BeforeClass + public void init() throws IOException, InterruptedException { + //Main.initLogging(false); + Configuration.autoDeobfuscate.set(false); + Configuration.decompile.set(true); + Configuration.registerNameFormat.set("_loc%d_"); + swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false); + } + + private void compareSrc(int frame, String expectedResult) { + DoActionTag doa = getFrameSource(frame); + assertNotNull(doa); + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + try { + Action.actionsToSource(doa, doa.getActions(), "", writer); + } catch (InterruptedException ex) { + fail(); + } + String actualResult = cleanPCode(writer.toString()); + expectedResult = cleanPCode(expectedResult); + assertEquals(actualResult, expectedResult); + + } + + private DoActionTag getFrameSource(int frame) { + int f = 0; + DoActionTag lastDoa = null; + + for (Tag t : swf.tags) { + if (t instanceof DoActionTag) { + lastDoa = (DoActionTag) t; + } + if (t instanceof ShowFrameTag) { + f++; + if (f == frame) { + return lastDoa; + } + lastDoa = null; + } + } + return null; + } + + @Test + public void frame23_Test() { + compareSrc(23, "stop();\r\n" + ); + } + + @Test + public void frame24_unicodeTest() { + compareSrc(24, "trace(\"unicodeTest\");\r\n" + + "var k = \"\u05d4\u05d9\u05e4\u05d5\u05e4\u05d5\u05d8\u05de\u05d9, \u05d0\u05d5 \u05d0\";\r\n" + + "trace(k);\r\n" + ); + } + + @Test + public void frame25_ifWithElseTest() { + compareSrc(25, "trace(\"ifWithElseTest\");\r\n" + + "var i = 5;\r\n" + + "if(i == 258)\r\n" + + "{\r\n" + + "trace(\"onTrue\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"onFalse\" + i);\r\n" + + "}\r\n" + ); + } + + @Test + public void frame26_forTest() { + compareSrc(26, "trace(\"forTest\");\r\n" + + "var i = 0;\r\n" + + "while(i < 10)\r\n" + + "{\r\n" + + "trace(\"hello:\" + i);\r\n" + + "i++;\r\n" + + "}\r\n" + ); + } + + @Test + public void frame27_whileTest() { + compareSrc(27, "trace(\"whileTest\");\r\n" + + "var i = 0;\r\n" + + "while(i < 10)\r\n" + + "{\r\n" + + "trace(\"hello:\" + i);\r\n" + + "i++;\r\n" + + "}\r\n" + ); + } + + @Test + public void frame28_forWithContinueTest() { + compareSrc(28, "trace(\"forWithContinueTest\");\r\n" + + "var i = 0;\r\n" + + "for(; i < 10; i++)\r\n" + + "{\r\n" + + "trace(\"hello:\" + i);\r\n" + + "if(i == 5)\r\n" + + "{\r\n" + + "trace(\"i==5\");\r\n" + + "if(i == 7)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"hawk\");\r\n" + + "}\r\n" + + "trace(\"end of the loop\");\r\n" + + "}\r\n" + ); + } + + @Test + public void frame29_doWhileTest() { + compareSrc(29, "trace(\"doWhileTest\");\r\n" + + "var i = 0;\r\n" + + "do\r\n" + + "{\r\n" + + "trace(\"i=\" + i);\r\n" + + "i++;\r\n" + + "}\r\n" + + "while(i < 10);\r\n" + + "trace(\"end\");\r\n" + ); + } + + @Test + public void frame30_switchTest() { + compareSrc(30, "trace(\"switchTest\");\r\n" + + "var i = 5;\r\n" + + "switch(i)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "case 1:\r\n" + + "trace(\"one\");\r\n" + + "break;\r\n" + + "case 2:\r\n" + + "trace(\"two\");\r\n" + + "case 3:\r\n" + + "trace(\"three\");\r\n" + + "break;\r\n" + + "case 4:\r\n" + + "trace(\"four\");\r\n" + + "break;\r\n" + + "default:\r\n" + + "trace(\"default clause\");\r\n" + + "}\r\n" + + "trace(\"scriptend\");\r\n" + ); + } + + @Test + public void frame31_strictEqualsTest() { + compareSrc(31, "trace(\"strictEqualsTest\");\r\n" + + "var i = 5;\r\n" + + "if(i === 5)\r\n" + + "{\r\n" + + "trace(\"equals strict\");\r\n" + + "}\r\n" + + "if(i !== 5)\r\n" + + "{\r\n" + + "trace(\"not equals strict\");\r\n" + + "}\r\n" + ); + } + + @Test + public void frame32_switchForTest() { + compareSrc(32, "trace(\"switchForTest\");\r\n" + + "var i = 0;\r\n" + + "for(; i < 10; i++)\r\n" + + "{\r\n" + + "switch(i)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "trace(\"zero\");\r\n" + + "continue;\r\n" + + "case 5:\r\n" + + "trace(\"five\");\r\n" + + "break;\r\n" + + "case 10:\r\n" + + "trace(\"ten\");\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "if(i == 7)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"one\");\r\n" + + "default:\r\n" + + "trace(\"def\");\r\n" + + "}\r\n" + + "trace(\"before loop end\");\r\n" + + "}\r\n" + ); + } + + @Test + public void frame33_functionTest() { + compareSrc(33, "function hello(what, second)\r\n" + + "{\r\n" + + "trace(\"hello \" + what + \"! \" + second);\r\n" + + "}\r\n" + + "trace(\"functionTest\");\r\n" + + "hello(\"friend\",7);\r\n" + ); + } + + @Test + public void frame34_multipleConditionsTest() { + compareSrc(34, "trace(\"multipleConditionsTest\");\r\n" + + "var k = 5;\r\n" + + "if(k == 7 && k == 8)\r\n" + + "{\r\n" + + "trace(\"first\");\r\n" + + "}\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"second\");\r\n" + + "}\r\n" + + "trace(\"finish\");\r\n" + ); + } + + @Test + public void frame35_multipleConditions2Test() { + compareSrc(35, "trace(\"multipleConditions2Test\");\r\n" + + "var k = 5;\r\n" + + "if(k == 7 && k == 8)\r\n" + + "{\r\n" + + "trace(\"first\");\r\n" + + "}\r\n" + + "if(k == 9 || k == 6)\r\n" + + "{\r\n" + + "trace(\"second\");\r\n" + + "}\r\n" + + "trace(\"finish\");\r\n" + ); + } + + @Test + public void frame36_chainedAssignmentsTest() { + compareSrc(36, "trace(\"chainedAssignmentsTest\");\r\n" + + "var a = 7;\r\n" + + "var b = 8;\r\n" + + "var c = 9;\r\n" + + "var d = c = b = a = 10;\r\n" + + "trace(d);\r\n" + ); + } + + @Test + public void frame37_objectsTest() { + compareSrc(37, "trace(\"objectsTest\");\r\n" + + "var flashBox = new Box(box1);\r\n" + + "_root.onEnterFrame = function()\r\n" + + "{\r\n" + + "flashBox.moveUp();\r\n" + + "};\r\n" + + "var ship = new Ship(200);\r\n" + + "var enemy = new Enemy(56);\r\n" + + "ship.moveDown(0.5);\r\n" + + "ship.moveUp(0.2);\r\n" + + "enemy.moveRight(230);\r\n" + + "enemy.moveLeft(100);\r\n" + + "var mt = new com.jpexs.MyTest();\r\n" + + "mt.test();\r\n" + + "var c = new Cox(box1);\r\n" + ); + } + + @Test + public void frame38_doWhile2Test() { + compareSrc(38, "trace(\"doWhile2Test\");\r\n" + + "var k = 5;\r\n" + + "do\r\n" + + "{\r\n" + + "k++;\r\n" + + "if(k == 7)\r\n" + + "{\r\n" + + "k = 5 * k;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "k = 5 + k;\r\n" + + "}\r\n" + + "}\r\n" + + "while(k < 9);\r\n" + ); + } + + @Test + public void frame39_whileAndTest() { + compareSrc(39, "trace(\"whileAndTest\");\r\n" + + "var a = 5;\r\n" + + "var b = 10;\r\n" + + "while(a < 10 && b > 1)\r\n" + + "{\r\n" + + "a++;\r\n" + + "b--;\r\n" + + "}\r\n" + + "a = 7;\r\n" + + "b = 9;\r\n" + ); + } + + @Test + public void frame40_forInTest() { + compareSrc(40, "function testForIn()\r\n" + + "{\r\n" + + "var _loc1_ = [];\r\n" + + "for(var _loc2_ in _loc1_)\r\n" + + "{\r\n" + + "if(_loc2_ > 3)\r\n" + + "{\r\n" + + "if(_loc2_ == 5)\r\n" + + "{\r\n" + + "return 7;\r\n" + + "}\r\n" + + "return 8;\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"forInTest\");\r\n" + + "trace(testForIn());\r\n" + + "var arr = [];\r\n" + + "for(var a in arr)\r\n" + + "{\r\n" + + "trace(a);\r\n" + + "}\r\n" + ); + } + + @Test + public void frame41_tryTest() { + compareSrc(41, "trace(\"tryTest\");\r\n" + + "var k = 5;\r\n" + + "try\r\n" + + "{\r\n" + + "k = Infinity;\r\n" + + "}\r\n" + + "catch(e)\r\n" + + "{\r\n" + + "trace(\"bug \" + e);\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"huu\");\r\n" + + "}\r\n" + + "trace(\"next\");\r\n" + + "try\r\n" + + "{\r\n" + + "k = 6;\r\n" + + "}\r\n" + + "catch(e)\r\n" + + "{\r\n" + + "trace(\"bug2 \" + e);\r\n" + + "}\r\n" + + "trace(\"next2\");\r\n" + + "var k = 5;\r\n" + + "try\r\n" + + "{\r\n" + + "k = Infinity;\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"final\");\r\n" + + "}\r\n" + + "trace(\"end\");\r\n" + ); + } + + @Test + public void frame42_indicesTest() { + compareSrc(42, "trace(\"indicesTest\");\r\n" + + "var k = [1,2,3];\r\n" + + "var b = k[1];\r\n" + + "trace(b);\r\n" + ); + } + + @Test + public void frame43_incDecTest() { + compareSrc(43, "function tst()\r\n" + + "{\r\n" + + "return 1;\r\n" + + "}\r\n" + + "trace(\"incDecTest\");\r\n" + + "var i = 5;\r\n" + + "var b = i++;\r\n" + + "var c = --i + 5;\r\n" + + "trace(\"a:\" + a + \" b:\" + b + \" c:\" + c);\r\n" + + "var arr = [1,2,3];\r\n" + + "arr[tst()]++;\r\n" + + "var d = arr[tst()];\r\n" + + "trace(d);\r\n" + ); + } + + @Test + public void frame44_chainedAssignments2Test() { + compareSrc(44, "trace(\"chainedAssignments2Test\");\r\n" + + "var a = 5;\r\n" + + "var b = 6;\r\n" + + "var c = 7;\r\n" + + "var d = c = b = a = 4;\r\n" + + "if((d = c = b = a = 7) > 2)\r\n" + + "{\r\n" + + "trace(d);\r\n" + + "}\r\n" + + "trace(d + 1);\r\n" + + "var i = 0;\r\n" + + "while(i < 5)\r\n" + + "{\r\n" + + "if(i == 7)\r\n" + + "{\r\n" + + "}\r\n" + + "i++;\r\n" + + "}\r\n" + ); + } + + @Test + public void frame45_function2Test() { + compareSrc(45, "function a()\r\n" + + "{\r\n" + + "trace(\"hi\");\r\n" + + "var _loc1_ = 5;\r\n" + + "if(_loc1_ == 7)\r\n" + + "{\r\n" + + "return undefined;\r\n" + + "}\r\n" + + "_loc1_ = _loc1_ * 9;\r\n" + + "trace(_loc1_);\r\n" + + "}\r\n" + + "trace(\"function2Test\");\r\n" + ); + } + + @Test + public void frame46_tryFunctionTest() { + compareSrc(46, "function testtry()\r\n" + + "{\r\n" + + "var _loc1_ = 5;\r\n" + + "try\r\n" + + "{\r\n" + + "if(_loc1_ == 3)\r\n" + + "{\r\n" + + "return undefined;\r\n" + + "}\r\n" + + "if(_loc1_ == 4)\r\n" + + "{\r\n" + + "throw new Error();\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "_loc1_ = 7;\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e)\r\n" + + "{\r\n" + + "trace(\"error\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"finally\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"tryFunctionTest\");\r\n" + ); + } + + @Test + public void frame47_ternarTest() { + compareSrc(47, "trace(\"ternarTest\");\r\n" + + "var a = 5;\r\n" + + "var b = a != 4?3:2;\r\n" + + "trace(b);\r\n" + ); + } + + @Test + public void frame48_forInInTest() { + compareSrc(48, "function tst()\r\n" + + "{\r\n" + + "var _loc2_ = [];\r\n" + + "_loc2_[0] = [];\r\n" + + "for(var _loc3_ in _loc2_)\r\n" + + "{\r\n" + + "for(var _loc1_ in _loc3_)\r\n" + + "{\r\n" + + "if(_loc1_ == 5)\r\n" + + "{\r\n" + + "return 5;\r\n" + + "}\r\n" + + "}\r\n" + + "if(_loc3_ == 8)\r\n" + + "{\r\n" + + "return 3;\r\n" + + "}\r\n" + + "}\r\n" + + "return 8;\r\n" + + "}\r\n" + + "trace(\"forInInTest\");\r\n" + + "tst();\r\n" + ); + } + + @Test + public void frame49_registersFuncTest() { + compareSrc(49, "function tst(px)\r\n" + + "{\r\n" + + "var _loc1_ = 57;\r\n" + + "_loc1_ = _loc1_ * 27;\r\n" + + "}\r\n" + + "trace(\"registersFuncTest\");\r\n" + + "tst(5);\r\n" + + "var s = String(5);\r\n" + ); + } + + @Test + public void frame50_ifFrameLoadedTest() { + compareSrc(50, "trace(\"ifFrameLoadedTest\");\r\n" + + "ifFrameLoaded(9)\r\n" + + "{\r\n" + + "trace(\"loaded\");\r\n" + + "}\r\n" + ); + } + + @Test + public void frame51_function3Test() { + compareSrc(51, "function tst()\r\n" + + "{\r\n" + + "var _loc1_ = 5;\r\n" + + "c = _loc1_ = 8;\r\n" + + "trace(\"hi\");\r\n" + + "trace(_loc1_);\r\n" + + "if((e = d = f = c = 9) > 5)\r\n" + + "{\r\n" + + "trace(\"dd\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"function3Test\");\r\n" + + "var c = 7;\r\n" + + "var d = 7;\r\n" + + "var e = 8;\r\n" + + "tst();\r\n" + ); + } + + @Test + public void frame52_commaOperatorTest() { + compareSrc(52, "trace(\"commaOperatorTest\");\r\n" + + "var a = 0;\r\n" + + "var b = 0;\r\n" + + "var c = 0;\r\n" + + "while(true)\r\n" + + "{\r\n" + + "a++;\r\n" + + "b = b + 2;\r\n" + + "if(c < 10)\r\n" + + "{\r\n" + + "trace(c);\r\n" + + "c++;\r\n" + + "continue;\r\n" + + "}\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"konec\");\r\n" + ); + } + + @Test + public void frame53_commaOperator2Test() { + compareSrc(53, "trace(\"commaOperator2Test\");\r\n" + + "var k = 8;\r\n" + + "do\r\n" + + "{\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"h\");\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"f\");\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"b\");\r\n" + + "}\r\n" + + "trace(\"gg\");\r\n" + + "}\r\n" + + "while(k++, k < 10);\r\n" + + "trace(\"ss\");\r\n" + ); + } + + @Test + public void frame54_function4Test() { + compareSrc(54, "function tst()\r\n" + + "{\r\n" + + "var _loc1_ = 5;\r\n" + + "while(_loc1_ < 10)\r\n" + + "{\r\n" + + "if(_loc1_ == 5)\r\n" + + "{\r\n" + + "if(_loc1_ == 6)\r\n" + + "{\r\n" + + "return true;\r\n" + + "}\r\n" + + "_loc1_ = _loc1_ + 1;\r\n" + + "continue;\r\n" + + "}\r\n" + + "return false;\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"function4Test\");\r\n" + + "tst();\r\n" + ); + } + + @Test + public void frame55_pushTest() { + compareSrc(55, "trace(\"pushTest\");\r\n" + + "53;" + ); + } + + @Test + public void frame56_commaOperator3Test() { + compareSrc(56, "trace(\"commaOperator3Test\");\r\n" + + "var k = 1;\r\n" + + "while(true)\r\n" + + "{\r\n" + + "k++;\r\n" + + "if(k < 10)\r\n" + + "{\r\n" + + "k = k * 5;\r\n" + + "trace(k);\r\n" + + "continue;\r\n" + + "}\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"end\");\r\n" + ); + } + + @Test + public void frame57_commaOperator4Test() { + compareSrc(57, "trace(\"commaOperator4Test\");\r\n" + + "var k = 0;\r\n" + + "do\r\n" + + "{\r\n" + + "trace(k);\r\n" + + "if(k == 8)\r\n" + + "{\r\n" + + "trace(\"a\");\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"d\");\r\n" + + "trace(\"b\");\r\n" + + "}\r\n" + + "k++;\r\n" + + "}\r\n" + + "while(k = k + 5, k < 20);\r\n" + + "trace(\"end\");\r\n" + ); + } + + @Test + public void frame58_globalFunctionsTest() { + compareSrc(58, "function tst(p1)\r\n" + + "{\r\n" + + "trace(\"test\");\r\n" + + "}\r\n" + + "trace(\"globalFunctionsTest\");\r\n" + + "var k = Array(1,2,3);\r\n" + + "var a = 1;\r\n" + + "var b = Boolean(a);\r\n" + + "call(5);\r\n" + + "var c = \"A\";\r\n" + + "clearInterval(5);\r\n" + + "clearTimeout(4);\r\n" + + "var mc;\r\n" + + "duplicateMovieClip(mc,\"copy\",16389);\r\n" + + "a = escape(\"how\");\r\n" + + "var f = a;\r\n" + + "fscommand(\"alert(\\\"hi\\\");\");\r\n" + + "a = mc._alpha;\r\n" + + "a = getTimer();\r\n" + + "getURL(\"http://localhost/\",\"wnd\",\"POST\");\r\n" + + "a = getVersion();\r\n" + + "gotoAndPlay(5);\r\n" + + "gotoAndStop(8);\r\n" + + "ifFrameLoaded(4)\r\n" + + "{\r\n" + + "trace(\"loaded\");\r\n" + + "}\r\n" + + "a = int(f);\r\n" + + "a = isFinite(f);\r\n" + + "a = isNaN(f);\r\n" + + "a = length(f);\r\n" + + "loadMovie(\"http://localhost/test.swf\",a,\"GET\");\r\n" + + "loadMovieNum(\"http://localhost/test.swf\",5,\"GET\");\r\n" + + "loadVariables(\"http://localhost/vars.txt\",a,\"GET\");\r\n" + + "loadVariablesNum(\"http://localhost/vars.txt\",4,\"GET\");\r\n" + + "a = mbchr(f);\r\n" + + "a = mblength(f);\r\n" + + "a = mbord(f);\r\n" + + "a = mbsubstring(\"aaaa\",5,4);\r\n" + + "MMExecute(\"destroyPC\");\r\n" + + "nextFrame();\r\n" + + "gotoAndStop(1);\r\n" + + "a = Number(f);\r\n" + + "a = Object(f);\r\n" + + "a = ord(f);\r\n" + + "a = parseFloat(f);\r\n" + + "a = parseInt(f,16);\r\n" + + "play();\r\n" + + "prevFrame();\r\n" + + "gotoAndStop(1);\r\n" + + "print(mc,\"bframe\");\r\n" + + "printAsBitmap(mc,\"bframe\");\r\n" + + "printAsBitmapNum(5,\"bframe\");\r\n" + + "printNum(4,\"bframe\");\r\n" + + "a = random(10);\r\n" + + "removeMovieClip(mc);\r\n" + + "setInterval(tst,5,f);\r\n" + + "mc._alpha = 25;\r\n" + + "setTimeout(tst,5,f);\r\n" + + "showRedrawRegions(false,0);\r\n" + + "startDrag(mc,1,5,5,6,6);\r\n" + + "stop();\r\n" + + "stopAllSounds();\r\n" + + "stopDrag();\r\n" + + "a = String(f);\r\n" + + "a = \"aa\";\r\n" + + "targetPath(f);\r\n" + + "tellTarget(mc)\r\n" + + "{\r\n" + + "trace(\"told\");\r\n" + + "}\r\n" + + "toggleHighQuality();\r\n" + + "a = unescape(f);\r\n" + + "unloadMovie(mc);\r\n" + + "unloadMovieNum(4);\r\n" + + "updateAfterEvent();\r\n" + ); + } + + @Test + public void frame59_unaryOpTest() { + compareSrc(59, "trace(\"unaryOpTest\");\r\n" + + "var a = 5;\r\n" + + "var c = ~a;\r\n" + + "var d = ~(a + c);\r\n" + + "var e = - c;\r\n" + ); + } +} diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex b/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex index a1760063a..870340e7c 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex @@ -17,8 +17,8 @@ package jsyntaxpane.lexers; import jsyntaxpane.Token; import jsyntaxpane.TokenType; - -%% + +%% %public %class ActionScriptLexer @@ -58,7 +58,7 @@ InputCharacter = [^\r\n] WhiteSpace = {LineTerminator} | [ \t\f]+ /* comments */ -Comment = {TraditionalComment} | {EndOfLineComment} +Comment = {TraditionalComment} | {EndOfLineComment} TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/" EndOfLineComment = "//" {InputCharacter}* {LineTerminator}? @@ -92,13 +92,13 @@ HexDigit = [0-9a-fA-F] OctIntegerLiteral = 0+ [1-3]? {OctDigit} {1,15} OctDigit = [0-7] - -/* floating point literals */ + +/* floating point literals */ DoubleLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}? -FLit1 = [0-9]+ \. [0-9]* -FLit2 = \. [0-9]+ -FLit3 = [0-9]+ +FLit1 = [0-9]+ \. [0-9]* +FLit2 = \. [0-9]+ +FLit3 = [0-9]+ Exponent = [eE] [+-]? [0-9]+ NewVector = "new" {WhiteSpace}* "<" @@ -108,6 +108,7 @@ StringCharacter = [^\r\n\"\\] SingleCharacter = [^\r\n\'\\] OIdentifierCharacter = [^\r\n\u00A7\\] +Preprocessor = \u00A7\u00A7 {Identifier} %state STRING, CHARLITERAL, XMLSTARTTAG, XML, OIDENTIFIER @@ -174,114 +175,117 @@ OIdentifierCharacter = [^\r\n\u00A7\\] "}" { return token(TokenType.OPERATOR, -CURLY); } "[" { return token(TokenType.OPERATOR, BRACKET); } "]" { return token(TokenType.OPERATOR, -BRACKET); } - ";" | - "," | - "..." | - "." | - "=" | - ">" | + ";" | + "," | + "..." | + "." | + "=" | + ">" | "<" | - "!" | - "~" | - "?" | - ":" | - "==" | - "<=" | - ">=" | - "!=" | - "&&" | - "||" | - "++" | - "--" | - "+" | - "-" | - "*" | - "/" | - "&" | - "|" | - "^" | - "%" | - "<<" | - ">>" | - ">>>" | - "+=" | - "-=" | - "*=" | - "/=" | - "&=" | - "|=" | - "^=" | - "%=" | - "<<=" | - ">>=" | + "!" | + "~" | + "?" | + ":" | + "==" | + "<=" | + ">=" | + "!=" | + "&&" | + "||" | + "++" | + "--" | + "+" | + "-" | + "*" | + "/" | + "&" | + "|" | + "^" | + "%" | + "<<" | + ">>" | + ">>>" | + "+=" | + "-=" | + "*=" | + "/=" | + "&=" | + "|=" | + "^=" | + "%=" | + "<<=" | + ">>=" | ">>>=" | - "as" | - "delete" | - "instanceof" | - "is" | - "::" | - "new" | - "typeof" | - "void" | + "as" | + "delete" | + "instanceof" | + "is" | + "::" | + "new" | + "typeof" | + "void" | {NewVector} | - "@" { return token(TokenType.OPERATOR); } - + "@" { return token(TokenType.OPERATOR); } + /* string literal */ - \" { - yybegin(STRING); - tokenStart = yychar; - tokenLength = 1; + \" { + yybegin(STRING); + tokenStart = yychar; + tokenLength = 1; } - "\u00A7" { - yybegin(OIDENTIFIER); - tokenStart = yychar; - tokenLength = 1; + {Preprocessor} { + return token(TokenType.REGEX); + } + "\u00A7" { + yybegin(OIDENTIFIER); + tokenStart = yychar; + tokenLength = 1; } /* character literal */ - \' { - yybegin(CHARLITERAL); - tokenStart = yychar; - tokenLength = 1; + \' { + yybegin(CHARLITERAL); + tokenStart = yychar; + tokenLength = 1; } /* numeric literals */ {DecIntegerLiteral} | - + {HexIntegerLiteral} | - + {OctIntegerLiteral} | - + {DoubleLiteral} | {DoubleLiteral}[dD] { return token(TokenType.NUMBER); } - + // JavaDoc comments need a state so that we can highlight the @ controls /* comments */ {Comment} { return token(TokenType.COMMENT); } /* whitespace */ - {WhiteSpace} { } + {WhiteSpace} { } {TypeNameSpec} { return token(TokenType.IDENTIFIER); } - {XMLBeginOneTag} { yybegin(XML); + {XMLBeginOneTag} { yybegin(XML); tokenStart = yychar; - tokenLength = yylength(); - String s=yytext(); + tokenLength = yylength(); + String s=yytext(); s=s.substring(1,s.length()-1); if(s.contains(" ")){ s=s.substring(0,s.indexOf(" ")); } xmlTagName = s; } - /*{XMLBeginTag} { yybegin(XMLSTARTTAG); + /*{XMLBeginTag} { yybegin(XMLSTARTTAG); tokenStart = yychar; - tokenLength = yylength(); - String s=yytext(); + tokenLength = yylength(); + String s=yytext(); xmlTagName = s.substring(1); }*/ - /* identifiers */ - {Identifier} { return token(TokenType.IDENTIFIER); } + /* identifiers */ + {Identifier} { return token(TokenType.IDENTIFIER); } } { @@ -293,7 +297,7 @@ OIdentifierCharacter = [^\r\n\u00A7\\] {XMLBeginOneTag} { tokenLength += yylength();} {XMLEndTag} { tokenLength += yylength(); String endtagname=yytext(); - endtagname=endtagname.substring(2,endtagname.length()-1); + endtagname=endtagname.substring(2,endtagname.length()-1); if(endtagname.equals(xmlTagName)){ yybegin(YYINITIAL); return token(TokenType.STRING, tokenStart, tokenLength); @@ -303,16 +307,16 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \" { - yybegin(YYINITIAL); + \" { + yybegin(YYINITIAL); // length also includes the trailing quote return token(TokenType.STRING, tokenStart, tokenLength + 1); } - + {StringCharacter}+ { tokenLength += yylength(); } \\[0-3]?{OctDigit}?{OctDigit} { tokenLength += yylength(); } - + /* escape sequences */ \\. { tokenLength += 2; } @@ -320,15 +324,15 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - "\u00A7" { - yybegin(YYINITIAL); + "\u00A7" { + yybegin(YYINITIAL); // length also includes the trailing quote return token(TokenType.REGEX, tokenStart, tokenLength + 1); } - + {OIdentifierCharacter}+ { tokenLength += yylength(); } - + /* escape sequences */ \\. { tokenLength += 2; } @@ -336,14 +340,14 @@ OIdentifierCharacter = [^\r\n\u00A7\\] } { - \' { - yybegin(YYINITIAL); + \' { + yybegin(YYINITIAL); // length also includes the trailing quote return token(TokenType.STRING, tokenStart, tokenLength + 1); } - + {SingleCharacter}+ { tokenLength += yylength(); } - + /* escape sequences */ \\. { tokenLength += 2; } From 47578bd13faa15d3a07862e1169e0a37099f683a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 7 Jun 2015 09:37:48 +0200 Subject: [PATCH 08/20] AS3: Better Alchemy / DomainMemory instruction handling --- .../instructions/alchemy/AlchemyTypeIns.java | 27 ++++ .../avm2/instructions/alchemy/Lf32Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Lf64Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Li16Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Li32Ins.java | 116 ++++++++--------- .../abc/avm2/instructions/alchemy/Li8Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Sf32Ins.java | 118 +++++++++--------- .../avm2/instructions/alchemy/Sf64Ins.java | 118 +++++++++--------- .../avm2/instructions/alchemy/Si16Ins.java | 118 +++++++++--------- .../avm2/instructions/alchemy/Si32Ins.java | 118 +++++++++--------- .../abc/avm2/instructions/alchemy/Si8Ins.java | 118 +++++++++--------- .../avm2/instructions/alchemy/Sxi16Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Sxi1Ins.java | 116 ++++++++--------- .../avm2/instructions/alchemy/Sxi8Ins.java | 116 ++++++++--------- .../abc/avm2/model/AlchemyLoadAVM2Item.java | 52 +++++++- .../avm2/model/AlchemySignExtendAVM2Item.java | 40 ++++-- .../abc/avm2/model/AlchemyStoreAVM2Item.java | 47 ++++++- .../flash/abc/types/traits/TraitClass.java | 7 ++ 18 files changed, 915 insertions(+), 776 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java new file mode 100644 index 000000000..2f7890b38 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +/** + * + * @author JPEXS + */ +public interface AlchemyTypeIns { + + public static final String ALCHEMY_PACKAGE = "avm2.intrinsics.memory"; + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf32Ins.java index 6739f5d58..215c47c7f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf32Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Lf32Ins extends InstructionDefinition { - - public Lf32Ins() { - super(0x38, "lf32", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Lf32Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Lf32Ins() { + super(0x38, "lf32", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'f', 32)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf64Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf64Ins.java index 33b88d996..9b971e5a5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf64Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Lf64Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Lf64Ins extends InstructionDefinition { - - public Lf64Ins() { - super(0x39, "lf64", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Lf64Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Lf64Ins() { + super(0x39, "lf64", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'f', 64)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li16Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li16Ins.java index 327dcafe8..44a3c0267 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li16Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li16Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Li16Ins extends InstructionDefinition { - - public Li16Ins() { - super(0x36, "li16", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Li16Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Li16Ins() { + super(0x36, "li16", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'i', 16)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li32Ins.java index 1f9086b89..e38c32477 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li32Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Li32Ins extends InstructionDefinition { - - public Li32Ins() { - super(0x37, "li32", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Li32Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Li32Ins() { + super(0x37, "li32", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'i', 32)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li8Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li8Ins.java index 3d4d7aef6..6987e579a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li8Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Li8Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Li8Ins extends InstructionDefinition { - - public Li8Ins() { - super(0x35, "li8", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Li8Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Li8Ins() { + super(0x35, "li8", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + stack.push(new AlchemyLoadAVM2Item(ins, ofs, 'i', 8)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java index 3600a9a38..c4b738610 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sf32Ins extends InstructionDefinition { - - public Sf32Ins() { - super(0x3D, "sf32", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sf32Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sf32Ins() { + super(0x3D, "sf32", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'f', 32)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java index b3ab4aafd..aff8f6ed1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sf64Ins extends InstructionDefinition { - - public Sf64Ins() { - super(0x3E, "sf64", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sf64Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sf64Ins() { + super(0x3E, "sf64", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'f', 64)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java index 94a030a38..b8719b254 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Si16Ins extends InstructionDefinition { - - public Si16Ins() { - super(0x3B, "si16", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Si16Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Si16Ins() { + super(0x3B, "si16", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'i', 16)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java index 2c02aed1f..ef7124bd1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Si32Ins extends InstructionDefinition { - - public Si32Ins() { - super(0x3C, "si32", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Si32Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Si32Ins() { + super(0x3C, "si32", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'i', 32)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java index 32a14bc3b..9a10cda59 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java @@ -1,59 +1,59 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Si8Ins extends InstructionDefinition { - - public Si8Ins() { - super(0x3A, "si8", new int[]{}, true); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem ofs = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Si8Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Si8Ins() { + super(0x3A, "si8", new int[]{}, true); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem ofs = stack.pop(); + GraphTargetItem value = stack.pop(); + output.add(new AlchemyStoreAVM2Item(ins, value, ofs, 'i', 8)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi16Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi16Ins.java index b52e0d8f0..fa63166b5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi16Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi16Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sxi16Ins extends InstructionDefinition { - - public Sxi16Ins() { - super(0x52, "sxi_16", new int[]{}, false); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem value = stack.pop(); - stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sxi16Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sxi16Ins() { + super(0x52, "sxi16", new int[]{}, false); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem value = stack.pop(); + stack.push(new AlchemySignExtendAVM2Item(ins, value, 16)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi1Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi1Ins.java index 434b7e479..e3a792330 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi1Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi1Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sxi1Ins extends InstructionDefinition { - - public Sxi1Ins() { - super(0x50, "sxi_1", new int[]{}, false); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem value = stack.pop(); - stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sxi1Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sxi1Ins() { + super(0x50, "sxi1", new int[]{}, false); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem value = stack.pop(); + stack.push(new AlchemySignExtendAVM2Item(ins, value, 1)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi8Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi8Ins.java index 90096eafd..3b6976421 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi8Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sxi8Ins.java @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Sxi8Ins extends InstructionDefinition { - - public Sxi8Ins() { - super(0x51, "sxi_8", new int[]{}, false); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return 1 - 1; - } - - @Override - public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { - return 0; - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem value = stack.pop(); - stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName)); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Sxi8Ins extends InstructionDefinition implements AlchemyTypeIns { + + public Sxi8Ins() { + super(0x51, "sxi8", new int[]{}, false); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return 1 - 1; + } + + @Override + public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { + return 0; + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem value = stack.pop(); + stack.push(new AlchemySignExtendAVM2Item(ins, value, 8)); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyLoadAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyLoadAVM2Item.java index 73525a4f6..b00b58b2a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyLoadAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyLoadAVM2Item.java @@ -16,11 +16,21 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf64Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li8Ins; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; /** * @@ -28,25 +38,57 @@ import com.jpexs.decompiler.graph.model.LocalData; */ public class AlchemyLoadAVM2Item extends AVM2Item { - private final String name; + private final char type; + private final int size; private final GraphTargetItem ofs; - public AlchemyLoadAVM2Item(GraphSourceItem instruction, GraphTargetItem ofs, String name) { + public AlchemyLoadAVM2Item(GraphSourceItem instruction, GraphTargetItem ofs, char type, int size) { super(instruction, PRECEDENCE_PRIMARY); - this.name = name; this.ofs = ofs; + this.type = type; + this.size = size; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("op_" + name + "("); + writer.append("l" + type + size + "("); ofs.toString(writer, localData); - return writer.append(") /*Alchemy*/"); + return writer.append(")"); + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + String ts = "" + type + size; + InstructionDefinition def = null; + switch (ts) { + case "i8": + def = new Li8Ins(); + break; + case "i16": + def = new Li16Ins(); + break; + case "i32": + def = new Li32Ins(); + break; + case "f": + def = new Lf32Ins(); + break; + case "f32": + def = new Lf64Ins(); + break; + } + return toSourceMerge(localData, generator, ofs, ins(def)); } @Override public GraphTargetItem returnType() { + switch (type) { + case 'i': + return new TypeItem("int"); + case 'f': + return new TypeItem("Number"); + } return TypeItem.UNBOUNDED; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemySignExtendAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemySignExtendAVM2Item.java index ed725c54a..18095c337 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemySignExtendAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemySignExtendAVM2Item.java @@ -12,14 +12,23 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi1Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi8Ins; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; /** * @@ -27,28 +36,45 @@ import com.jpexs.decompiler.graph.model.LocalData; */ public class AlchemySignExtendAVM2Item extends AVM2Item { - private final String name; + private final int size; - public AlchemySignExtendAVM2Item(GraphSourceItem instruction, GraphTargetItem value, String name) { + public AlchemySignExtendAVM2Item(GraphSourceItem instruction, GraphTargetItem value, int size) { super(instruction, PRECEDENCE_PRIMARY); - this.name = name; this.value = value; + this.size = size; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("op_" + name + "("); + writer.append("si" + size + "("); value.toString(writer, localData); - return writer.append(") /*Alchemy*/"); + return writer.append(")"); } @Override public GraphTargetItem returnType() { - return TypeItem.UNBOUNDED; + return new TypeItem("int"); } @Override public boolean hasReturnValue() { return true; } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + InstructionDefinition def = null; + switch (size) { + case 1: + def = new Sxi1Ins(); + break; + case 8: + def = new Sxi8Ins(); + break; + case 16: + def = new Sxi16Ins(); + break; + } + return toSourceMerge(localData, generator, value, ins(def)); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyStoreAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyStoreAVM2Item.java index d36499f38..e26570594 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyStoreAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AlchemyStoreAVM2Item.java @@ -16,11 +16,21 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf64Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si8Ins; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; /** * @@ -28,24 +38,26 @@ import com.jpexs.decompiler.graph.model.LocalData; */ public class AlchemyStoreAVM2Item extends AVM2Item { - private final String name; + private final char type; + private final int size; private final GraphTargetItem ofs; - public AlchemyStoreAVM2Item(GraphSourceItem instruction, GraphTargetItem value, GraphTargetItem ofs, String name) { + public AlchemyStoreAVM2Item(GraphSourceItem instruction, GraphTargetItem value, GraphTargetItem ofs, char type, int size) { super(instruction, PRECEDENCE_PRIMARY); - this.name = name; this.ofs = ofs; this.value = value; + this.type = type; + this.size = size; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("op_" + name + "("); + writer.append("s" + type + size + "("); ofs.toString(writer, localData); writer.append(","); value.toString(writer, localData); - return writer.append(") /*Alchemy*/"); + return writer.append(")"); } @Override @@ -57,4 +69,29 @@ public class AlchemyStoreAVM2Item extends AVM2Item { public boolean hasReturnValue() { return false; } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + String ts = "" + type + size; + InstructionDefinition def = null; + switch (ts) { + case "i8": + def = new Si8Ins(); + break; + case "i16": + def = new Si16Ins(); + break; + case "i32": + def = new Si32Ins(); + break; + case "f32": + def = new Sf32Ins(); + break; + case "f64": + def = new Sf64Ins(); + break; + } + return toSourceMerge(localData, generator, ofs, ins(def)); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index ee2659131..af40b017d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ClassPath; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.AlchemyTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns; @@ -270,6 +271,12 @@ public class TraitClass extends Trait implements TraitWithSlot { parseImportsUsagesFromMultiname(abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames); } for (AVM2Instruction ins : body.getCode().code) { + if (ins.definition instanceof AlchemyTypeIns) { + String nimport = AlchemyTypeIns.ALCHEMY_PACKAGE + "." + ins.definition.instructionName; + if (!imports.contains(nimport)) { + imports.add(nimport); + } + } if (ins.definition instanceof NewFunctionIns) { if (ins.operands[0] != method_index) { if (!visitedMethods.contains(ins.operands[0])) { From 650aefede221d13e143e7e578b8f7b124c264895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 7 Jun 2015 13:46:15 +0200 Subject: [PATCH 09/20] Better multi packs handling (Alchemy) - direct editing allowed Better package/class splitting for obfuscated names --- .../com/jpexs/decompiler/flash/abc/ABC.java | 67 +- .../decompiler/flash/abc/ScriptPack.java | 1 + .../model/clauses/DeclarationAVM2Item.java | 4 +- .../abc/avm2/model/clauses/TryAVM2Item.java | 2 +- .../parser/script/AVM2SourceGenerator.java | 30 +- .../parser/script/ActionScriptParser.java | 106 +- .../abc/avm2/parser/script/ClassAVM2Item.java | 5 +- .../avm2/parser/script/InterfaceAVM2Item.java | 5 +- .../avm2/parser/script/PackageAVM2Item.java | 5 +- .../avm2/parser/script/PropertyAVM2Item.java | 3 +- .../parser/script/UnresolvedAVM2Item.java | 40 +- .../flash/abc/types/InstanceInfo.java | 280 +- .../flash/abc/types/MethodInfo.java | 2 +- .../decompiler/flash/abc/types/Multiname.java | 19 +- .../flash/abc/types/ScriptInfo.java | 3 + .../flash/abc/types/traits/Trait.java | 400 +-- .../flash/abc/types/traits/TraitClass.java | 114 +- .../abc/usages/ClassNameMultinameUsage.java | 2 +- .../abc/usages/InsideClassMultinameUsage.java | 2 +- .../jpexs/decompiler/graph/DottedChain.java | 106 + .../com/jpexs/decompiler/graph/TypeItem.java | 50 +- .../src/com/jpexs/helpers/Helper.java | 2656 +++++++------- src/com/jpexs/decompiler/flash/gui/Main.java | 3082 ++++++++--------- .../jpexs/decompiler/flash/gui/MainPanel.java | 2 + .../decompiler/flash/gui/abc/ABCPanel.java | 10 +- .../flash/gui/abc/DecompiledEditorPane.java | 12 +- .../decompiler/flash/gui/abc/UsageFrame.java | 358 +- .../flash/gui/debugger/DebuggerTools.java | 4 +- 28 files changed, 3747 insertions(+), 3623 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index 95678a188..2924eaacf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -59,17 +59,21 @@ import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.utf8.Utf8PrintWriter; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; +import javafx.collections.transformation.SortedList; public class ABC { @@ -107,7 +111,7 @@ public class ABC { public ABCContainerTag parentTag; /* Map from multiname index of namespace value to namespace name**/ - private Map namespaceMap; + private Map namespaceMap; public ABC(ABCContainerTag tag) { this.parentTag = tag; @@ -323,7 +327,7 @@ public class ABC { int mIndex = body.getCode().code.get(ip).operands[0]; if (mIndex > 0) { Multiname m = constants.getMultiname(mIndex); - if (m.getNameWithNamespace(constants, true).equals("flash.utils.getDefinitionByName")) { + if (m.getNameWithNamespace(constants).equals("flash.utils.getDefinitionByName")) { if (ip > 0) { if (body.getCode().code.get(ip - 1).definition instanceof PushStringIns) { int strIndex = body.getCode().code.get(ip - 1).operands[0]; @@ -812,16 +816,16 @@ public class ABC { } } - private Map getNamespaceMap() { + private Map getNamespaceMap() { if (namespaceMap == null) { - Map map = new HashMap<>(); + Map map = new HashMap<>(); for (ScriptInfo si : script_info) { for (Trait t : si.traits.traits) { if (t instanceof TraitSlotConst) { TraitSlotConst s = ((TraitSlotConst) t); if (s.isNamespace()) { String key = constants.getNamespace(s.value_index).getName(constants, true); // assume not null - String val = constants.getMultiname(s.name_index).getNameWithNamespace(constants, true); + DottedChain val = constants.getMultiname(s.name_index).getNameWithNamespace(constants); map.put(key, val); } } @@ -855,15 +859,15 @@ public class ABC { return bodyIdxFromMethodIdx; } - public String nsValueToName(String value) { + public DottedChain nsValueToName(String value) { if (getNamespaceMap().containsKey(value)) { return getNamespaceMap().get(value); } else { String ns = getDeobfuscation().builtInNs(value); if (ns == null) { - return ""; + return new DottedChain(""); } else { - return ns; + return new DottedChain(ns); } } } @@ -1037,8 +1041,8 @@ public class ABC { public int findClassByName(String name) { for (int c = 0; c < instance_info.size(); c++) { - String s = constants.getMultiname(instance_info.get(c).name_index).getNameWithNamespace(constants, true); - if (name.equals(s)) { + DottedChain s = constants.getMultiname(instance_info.get(c).name_index).getNameWithNamespace(constants); + if (name.equals(s.toString())) { return c; } } @@ -1229,31 +1233,54 @@ public class ABC { method_info.remove(index); } - public void replaceScriptPack(ScriptPack pack, String as) throws AVM2ParseException, CompilationException, IOException, InterruptedException { + public boolean replaceScriptPack(ScriptPack pack, String as) throws AVM2ParseException, CompilationException, IOException, InterruptedException { String scriptName = pack.getPathScriptName() + ".as"; int oldIndex = pack.scriptIndex; int newIndex = script_info.size(); String documentClass = getSwf().getDocumentClass(); boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString()); + boolean isSimple = pack.isSimple; + ScriptInfo si = script_info.get(oldIndex); - si.delete(this, true); - int newClassIndex = instance_info.size(); - for (Trait t : si.traits.traits) { - if (t instanceof TraitClass) { - TraitClass tc = (TraitClass) t; - newClassIndex = tc.class_info + 1; + if (isSimple) { + si.delete(this, true); + } else { + for (int t : pack.traitIndices) { + si.traits.traits.get(t).delete(this, true); } } + + int newClassIndex = instance_info.size(); + for (int t : pack.traitIndices) { + if (si.traits.traits.get(t) instanceof TraitClass) { + TraitClass tc = (TraitClass) si.traits.traits.get(t); + newClassIndex = tc.class_info + 1; + } + + } List otherAbcs = new ArrayList<>(pack.allABCs); + otherAbcs.remove(this); ActionScriptParser.compile(as, this, otherAbcs, isDocumentClass, scriptName, newClassIndex); - // Move newly added script to its position - script_info.set(oldIndex, script_info.get(newIndex)); - script_info.remove(newIndex); + + if (isSimple) { + // Move newly added script to its position + script_info.set(oldIndex, script_info.get(newIndex)); + script_info.remove(newIndex); + } else { + script_info.get(newIndex).setModified(true); + //Note: Is deleting traits safe? + List todel = new ArrayList<>(new TreeSet<>(pack.traitIndices)); + for (int i = todel.size() - 1; i >= 0; i--) { + si.traits.traits.remove((int) todel.get(i)); + } + } + script_info.get(oldIndex).setModified(true); pack(); // removes old classes/methods ((Tag) parentTag).setModified(true); + return !isSimple; } public void pack() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 684204afe..1c3a8f470 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -61,6 +61,7 @@ public class ScriptPack extends AS3ClassTreeItem { public final List traitIndices; private final ClassPath path; + public boolean isSimple = false; @Override public SWF getSwf() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java index 32d64eaad..956ecd8d6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java @@ -85,7 +85,7 @@ public class DeclarationAVM2Item extends AVM2Item { if (lti.value instanceof ConvertAVM2Item) { coerType = ((ConvertAVM2Item) lti.value).type; } - srcData.declaredType = (coerType instanceof TypeItem) ? ((TypeItem) coerType).fullTypeName : "*"; + srcData.declaredType = (coerType instanceof TypeItem) ? ((TypeItem) coerType).fullTypeName.toPrintableString() : "*"; writer.append("var "); writer.append(localName); writer.append(":"); @@ -97,7 +97,7 @@ public class DeclarationAVM2Item extends AVM2Item { SetSlotAVM2Item ssti = (SetSlotAVM2Item) assignment; srcData.localName = ssti.getNameAsStr(localData); srcData.declaration = true; - srcData.declaredType = (type instanceof TypeItem) ? ((TypeItem) type).fullTypeName : "*"; + srcData.declaredType = (type instanceof TypeItem) ? ((TypeItem) type).fullTypeName.toPrintableString() : "*"; writer.append("var "); ssti.getName(writer, localData); writer.append(":"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java index 3e223f4a1..ab8a69b17 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java @@ -96,7 +96,7 @@ public class TryAVM2Item extends AVM2Item implements Block { int eti = catchExceptions.get(e).type_index; - data.declaredType = eti <= 0 ? "*" : localData.constantsAvm2.constant_multiname.get(eti).getNameWithNamespace(localData.constantsAvm2, true); + data.declaredType = eti <= 0 ? "*" : localData.constantsAvm2.constant_multiname.get(eti).getNameWithNamespace(localData.constantsAvm2).toPrintableString(); writer.hilightSpecial(localName, HighlightSpecialType.TRY_NAME, e, data); writer.append(":"); writer.hilightSpecial(catchExceptions.get(e).getTypeName(localData.constantsAvm2, localData.fullyQualifiedNames), HighlightSpecialType.TRY_TYPE, e); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 13a7d5188..37c42df8c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -108,6 +108,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.Loop; @@ -1194,7 +1195,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return abc; } - public void generateClass(List importedClasses, List sinitVariables, boolean staticNeedsActivation, List staticInit, List openedNamespaces, int namespace, int initScope, String pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List traitItems, Reference class_index) throws AVM2ParseException, CompilationException { + public void generateClass(List importedClasses, List sinitVariables, boolean staticNeedsActivation, List staticInit, List openedNamespaces, int namespace, int initScope, String pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List traitItems, Reference class_index) throws AVM2ParseException, CompilationException { localData.currentClass = name; localData.pkg = pkg; List ret = new ArrayList<>(); @@ -1706,7 +1707,7 @@ public class AVM2SourceGenerator implements SourceGenerator { TraitSlotConst tsc = (TraitSlotConst) mbody.traits.traits.get(i); GraphTargetItem type = TypeItem.UNBOUNDED; if (tsc.type_index > 0) { - type = new TypeItem(abc.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(abc.constants, true)); + type = new TypeItem(abc.constants.constant_multiname.get(tsc.type_index).getNameWithNamespace(abc.constants)); } NameAVM2Item d = new NameAVM2Item(type, 0, tsc.getName(abc).getName(abc.constants, new ArrayList<>(), true), NameAVM2Item.getDefaultValue("" + type), true, new ArrayList()); d.setSlotNumber(tsc.slot_id); @@ -1867,7 +1868,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return null; } - private int genNs(List importedClasses, String pkg, String custom, int namespace, List openedNamespaces, SourceGeneratorLocalData localData, int line) throws CompilationException { + private int genNs(List importedClasses, String pkg, String custom, int namespace, List openedNamespaces, SourceGeneratorLocalData localData, int line) throws CompilationException { if (custom != null) { PropertyAVM2Item prop = new PropertyAVM2Item(null, custom, abc, allABCs, openedNamespaces, new ArrayList()); Reference value = new Reference<>(null); @@ -1878,11 +1879,9 @@ public class AVM2SourceGenerator implements SourceGenerator { } if (!resolved) { - String customPkg = ""; - String fullCustom = ""; - for (String imp : importedClasses) { - if (imp.endsWith("." + custom)) { - customPkg = imp.substring(0, imp.lastIndexOf('.')); + DottedChain fullCustom = null; + for (DottedChain imp : importedClasses) { + if (imp.getLast().equals(custom)) { fullCustom = imp; break; } @@ -1895,7 +1894,7 @@ public class AVM2SourceGenerator implements SourceGenerator { for (ScriptInfo si : a.script_info) { for (Trait t : si.traits.traits) { Multiname m = t.getName(a); - if (fullCustom.equals(m.getNameWithNamespace(a.constants, true))) { + if (fullCustom != null && fullCustom.equals(m.getNameWithNamespace(a.constants))) { if (t instanceof TraitSlotConst) { if (((TraitSlotConst) t).isNamespace()) { Namespace ns = a.constants.getNamespace(((TraitSlotConst) t).value_index); @@ -1914,7 +1913,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return namespace; } - public void generateTraitsPhase2(List importedClasses, String pkg, List items, Trait[] traits, List openedNamespaces, SourceGeneratorLocalData localData) throws CompilationException { + public void generateTraitsPhase2(List importedClasses, String pkg, List items, Trait[] traits, List openedNamespaces, SourceGeneratorLocalData localData) throws CompilationException { for (int k = 0; k < items.size(); k++) { GraphTargetItem item = items.get(k); if (traits[k] == null) { @@ -2145,7 +2144,7 @@ public class AVM2SourceGenerator implements SourceGenerator { ScriptInfo si = new ScriptInfo(); localData.currentScript = si; Trait[] traitArr = generateTraitsPhase1(null, null, true, localData, commands, si.traits, class_index); - generateTraitsPhase2(new ArrayList<>(), null/*FIXME*/, commands, traitArr, new ArrayList(), localData); + generateTraitsPhase2(new ArrayList(), null/*FIXME*/, commands, traitArr, new ArrayList(), localData); MethodInfo mi = new MethodInfo(new int[0], 0, 0, 0, new ValueKind[0], new int[0]); MethodBody mb = new MethodBody(); mb.method_info = abc.addMethodInfo(mi); @@ -2457,12 +2456,9 @@ public class AVM2SourceGenerator implements SourceGenerator { TypeItem type = (TypeItem) typeItem; - String name = type.fullTypeName; - String pkg = ""; - if (name.contains(".")) { - pkg = name.substring(0, name.lastIndexOf('.')); - name = name.substring(name.lastIndexOf('.') + 1); - } + DottedChain dname = type.fullTypeName; + String pkg = dname.getWithoutLast().toString(); + String name = dname.getLast(); for (InstanceInfo ii : abc.instance_info) { Multiname mname = abc.constants.constant_multiname.get(ii.name_index); if (mname != null && name.equals(mname.getName(abc.constants, new ArrayList<>(), true))) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java index f20e46a4c..4924fd921 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java @@ -86,6 +86,7 @@ import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.Loop; import com.jpexs.decompiler.graph.TypeItem; @@ -144,7 +145,7 @@ public class ActionScriptParser { return uniqLast; } - private List commands(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, AVM2ParseException { + private List commands(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, AVM2ParseException { List ret = new ArrayList<>(); if (debugMode) { System.out.println("commands:"); @@ -159,7 +160,7 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem type(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem type(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List variables) throws IOException, AVM2ParseException { ParsedSymbol s = lex(); if (s.type == SymbolType.MULTIPLY) { return new UnboundedTypeItem(); @@ -174,7 +175,7 @@ public class ActionScriptParser { return t; } - private GraphTargetItem memberOrCall(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem memberOrCall(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { if (debugMode) { System.out.println("memberOrCall:"); } @@ -223,7 +224,7 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem applyType(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem applyType(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { GraphTargetItem ret = obj; ParsedSymbol s = lex(); if (s.type == SymbolType.TYPENAME) { @@ -250,7 +251,7 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem member(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem member(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { if (debugMode) { System.out.println("member:"); } @@ -286,7 +287,7 @@ public class ActionScriptParser { s = lex(); GraphTargetItem ns = null; if (s.type == SymbolType.NAMESPACE_OP) { - ns = new UnresolvedAVM2Item(new ArrayList(), importedClasses, false, null, lexer.yyline(), propName, null, openedNamespaces); + ns = new UnresolvedAVM2Item(new ArrayList(), importedClasses, false, null, lexer.yyline(), new DottedChain(propName), null, openedNamespaces); variables.add((UnresolvedAVM2Item) ns); s = lex(); if (s.type == SymbolType.BRACKET_OPEN) { @@ -317,28 +318,31 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem name(TypeItem thisType, String pkg, Reference needsActivation, boolean typeOnly, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, List importedClasses) throws IOException, AVM2ParseException { + private GraphTargetItem name(TypeItem thisType, String pkg, Reference needsActivation, boolean typeOnly, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, List importedClasses) throws IOException, AVM2ParseException { ParsedSymbol s = lex(); - String name = ""; + DottedChain name = new DottedChain(); + String name2 = ""; if (s.type == SymbolType.ATTRIBUTE) { - name += "@"; + name2 += "@"; s = lex(); } expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.THIS, SymbolType.SUPER, SymbolType.STRING_OP); - name += s.value.toString(); + name2 += s.value.toString(); s = lex(); boolean attrBracket = false; + name.parts.add(name2); while (s.isType(SymbolType.DOT)) { - name += s.value.toString(); //. or :: + //name += s.value.toString(); //. or :: s = lex(); + name2 = ""; if (s.type == SymbolType.ATTRIBUTE) { - name += "@"; + name2 += "@"; s = lex(); if (s.type == SymbolType.MULTIPLY) { - name += s.value.toString(); + name2 += s.value.toString(); } else if (s.group == SymbolGroup.IDENTIFIER) { - name += s.value.toString(); + name2 += s.value.toString(); } else { if (s.type != SymbolType.BRACKET_OPEN) { throw new AVM2ParseException("Attribute identifier or bracket expected", lexer.yyline()); @@ -348,19 +352,16 @@ public class ActionScriptParser { } } else { expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE); - name += s.value.toString(); + name2 += s.value.toString(); } + name.parts.add(name2); s = lex(); } String nsname = null; String nsprop = null; GraphTargetItem nspropItem = null; if (s.type == SymbolType.NAMESPACE_OP) { - if (name.contains(".")) { - nsname = name.substring(name.lastIndexOf('.') + 1); - } else { - nsname = name; - } + nsname = name.getLast(); s = lex(); if (s.group == SymbolGroup.IDENTIFIER) { nsprop = s.value.toString(); @@ -368,16 +369,12 @@ public class ActionScriptParser { nspropItem = expression(thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables); expectedType(SymbolType.BRACKET_CLOSE); } - if (name.contains(".")) { - name = name.substring(0, name.lastIndexOf('.')); - } else { - name = null; - } + name = name.getWithoutLast(); s = lex(); } GraphTargetItem ret = null; - if (name != null) { + if (!name.parts.isEmpty()) { UnresolvedAVM2Item unr = new UnresolvedAVM2Item(new ArrayList(), importedClasses, typeOnly, null, lexer.yyline(), name, null, openedNamespaces); //unr.setIndex(index); variables.add(unr); @@ -388,7 +385,7 @@ public class ActionScriptParser { if (attr) { nsname = nsname.substring(1); } - UnresolvedAVM2Item ns = new UnresolvedAVM2Item(new ArrayList(), importedClasses, typeOnly, null, lexer.yyline(), nsname, null, openedNamespaces); + UnresolvedAVM2Item ns = new UnresolvedAVM2Item(new ArrayList(), importedClasses, typeOnly, null, lexer.yyline(), new DottedChain(nsname), null, openedNamespaces); variables.add(ns); ret = new NamespacedAVM2Item(ns, nsprop, nspropItem, ret, attr, openedNamespaces, null); } @@ -443,7 +440,7 @@ public class ActionScriptParser { return ret; } - private List call(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private List call(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { List ret = new ArrayList<>(); //expected(SymbolType.PARENT_OPEN); //MUST BE HANDLED BY CALLER ParsedSymbol s = lex(); @@ -458,12 +455,12 @@ public class ActionScriptParser { return ret; } - private MethodAVM2Item method(String pkg, boolean isInterface, String customAccess, Reference needsActivation, List importedClasses, boolean override, boolean isFinal, TypeItem thisType, List openedNamespaces, boolean isStatic, int namespace, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { + private MethodAVM2Item method(String pkg, boolean isInterface, String customAccess, Reference needsActivation, List importedClasses, boolean override, boolean isFinal, TypeItem thisType, List openedNamespaces, boolean isStatic, int namespace, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { FunctionAVM2Item f = function(pkg, isInterface, needsActivation, importedClasses, namespace, thisType, openedNamespaces, functionName, isMethod, variables); return new MethodAVM2Item(f.pkg, f.isInterface, customAccess, f.needsActivation, f.hasRest, f.line, override, isFinal, isStatic, f.namespace, functionName, f.paramTypes, f.paramNames, f.paramValues, f.body, f.subvariables, f.retType); } - private FunctionAVM2Item function(String pkg, boolean isInterface, Reference needsActivation, List importedClasses, int namespace, TypeItem thisType, List openedNamespaces, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { + private FunctionAVM2Item function(String pkg, boolean isInterface, Reference needsActivation, List importedClasses, int namespace, TypeItem thisType, List openedNamespaces, String functionName, boolean isMethod, List variables) throws IOException, AVM2ParseException { openedNamespaces = new ArrayList<>(openedNamespaces); //local copy int line = lexer.yyline(); ParsedSymbol s; @@ -544,7 +541,7 @@ public class ActionScriptParser { return new FunctionAVM2Item(pkg, isInterface, needsActivation2.getVal(), namespace, hasRest, line, functionName, paramTypes, paramNames, paramValues, body, subvariables, retType); } - private GraphTargetItem traits(String scriptName, boolean scriptTraits, List sinitVariables, Reference sinitNeedsActivation, List staticInitializer, List importedClasses, int privateNs, int protectedNs, int publicNs, int packageInternalNs, int protectedStaticNs, List openedNamespaces, String pkg, String classNameStr, boolean isInterface, List traits) throws AVM2ParseException, IOException, CompilationException { + private GraphTargetItem traits(String scriptName, boolean scriptTraits, List sinitVariables, Reference sinitNeedsActivation, List staticInitializer, List importedClasses, int privateNs, int protectedNs, int publicNs, int packageInternalNs, int protectedStaticNs, List openedNamespaces, String pkg, String classNameStr, boolean isInterface, List traits) throws AVM2ParseException, IOException, CompilationException { ParsedSymbol s; GraphTargetItem constr = null; TypeItem thisType = pkg == null && classNameStr == null ? null : new TypeItem(pkg == null || "".equals(pkg) ? classNameStr : pkg + "." + classNameStr); @@ -892,7 +889,7 @@ public class ActionScriptParser { return constr; } - private GraphTargetItem classTraits(String scriptName, int gpublicNs, String pkg, List importedClasses, boolean isDynamic, boolean isFinal, List openedNamespaces, String packageName, int namespace, boolean isInterface, String nameStr, GraphTargetItem extendsStr, List implementsStr, List variables) throws IOException, AVM2ParseException, CompilationException { + private GraphTargetItem classTraits(String scriptName, int gpublicNs, String pkg, List importedClasses, boolean isDynamic, boolean isFinal, List openedNamespaces, String packageName, int namespace, boolean isInterface, String nameStr, GraphTargetItem extendsStr, List implementsStr, List variables) throws IOException, AVM2ParseException, CompilationException { GraphTargetItem ret = null; @@ -1049,7 +1046,7 @@ public class ActionScriptParser { } } - private List xmltag(TypeItem thisType, String pkg, Reference usesVars, List openedTags, Reference closedVarTags, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private List xmltag(TypeItem thisType, String pkg, Reference usesVars, List openedTags, Reference closedVarTags, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { ParsedSymbol s = null; List rets = new ArrayList<>(); //GraphTargetItem ret = null; @@ -1178,7 +1175,7 @@ public class ActionScriptParser { return rets; } - private GraphTargetItem xml(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem xml(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { List openedTags = new ArrayList<>(); int closedVarTags = 0; @@ -1189,7 +1186,7 @@ public class ActionScriptParser { return ret; } - private GraphTargetItem command(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem command(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables) throws IOException, AVM2ParseException { LexBufferer buf = new LexBufferer(); lexer.addListener(buf); GraphTargetItem ret = null; @@ -1672,7 +1669,7 @@ public class ActionScriptParser { } - private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { return expression(thisType, pkg, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, allowRemainder, variables); } @@ -1704,7 +1701,7 @@ public class ActionScriptParser { return ret; } - /*private GraphTargetItem expressionRemainder(TypeItem thisType, String pkg, Reference needsActivation, List openedNamespaces, GraphTargetItem expr, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, List importedClasses) throws IOException, AVM2ParseException { + /*private GraphTargetItem expressionRemainder(TypeItem thisType, String pkg, Reference needsActivation, List openedNamespaces, GraphTargetItem expr, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, List importedClasses) throws IOException, AVM2ParseException { GraphTargetItem ret = null; ParsedSymbol s = lex(); @@ -1740,7 +1737,7 @@ public class ActionScriptParser { return false; } - private int brackets(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List ret, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + private int brackets(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, List ret, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { ParsedSymbol s = lex(); int arrCnt = 0; if (s.type == SymbolType.BRACKET_OPEN) { @@ -1764,7 +1761,7 @@ public class ActionScriptParser { return arrCnt; } - private GraphTargetItem commaExpression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forInLevel, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem commaExpression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forInLevel, List variables) throws IOException, AVM2ParseException { GraphTargetItem cmd = null; List expr = new ArrayList<>(); ParsedSymbol s; @@ -1786,7 +1783,7 @@ public class ActionScriptParser { return new CommaExpressionItem(null, expr); } - private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { GraphTargetItem prim = expressionPrimary(thisType, pkg, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables); if (prim == null) { return null; @@ -1816,7 +1813,7 @@ public class ActionScriptParser { return lookahead; } - private GraphTargetItem expression1(GraphTargetItem lhs, int min_precedence, TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expression1(GraphTargetItem lhs, int min_precedence, TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { if (debugMode) { System.out.println("expression1:"); } @@ -2029,7 +2026,7 @@ public class ActionScriptParser { return lhs; } - private GraphTargetItem expressionPrimary(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { + private GraphTargetItem expressionPrimary(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { if (debugMode) { System.out.println("primary:"); } @@ -2279,39 +2276,34 @@ public class ActionScriptParser { s = lex(); } - List importedClasses = new ArrayList<>(); + List importedClasses = new ArrayList<>(); s = lex(); while (s.type == SymbolType.IMPORT) { - String impPackage = ""; - String impName = null; boolean all = false; s = lex(); expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER); - impName = s.value.toString(); + DottedChain imp = new DottedChain(); + imp.parts.add(s.value.toString()); s = lex(); + boolean isStar = false; while (s.type == SymbolType.DOT) { - if (!"".equals(impPackage)) { - impPackage += "."; - } - impPackage += impName; s = lex(); if (s.type == SymbolType.MULTIPLY) { - impName = null; + isStar = true; s = lex(); break; } expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER); - - impName = s.value.toString(); + imp.parts.add(s.value.toString()); s = lex(); } - if (impName == null) { - openedNamespaces.add(abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(impPackage, true)), 0, true)); + if (isStar) { + openedNamespaces.add(abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(imp.toString(), true)), 0, true)); } else { - importedClasses.add(impPackage + "." + impName); + importedClasses.add(imp); } expected(s, lexer.yyline(), SymbolType.SEMICOLON); @@ -2349,7 +2341,7 @@ public class ActionScriptParser { openedNamespaces.add(publicNs = abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId("", true)), 0, true)); List items = new ArrayList<>(); - traits(fileName, true, new ArrayList(), new Reference<>(false), new ArrayList(), new ArrayList<>(), scriptPrivateNs, 0, publicNs, 0, 0, openedNamespaces, null, null, false, items); + traits(fileName, true, new ArrayList(), new Reference<>(false), new ArrayList(), new ArrayList(), scriptPrivateNs, 0, publicNs, 0, 0, openedNamespaces, null, null, false, items); return items; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java index 719e7102c..cd49a855d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.Block; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -54,7 +55,7 @@ public class ClassAVM2Item extends AVM2Item implements Block { public List sinitVariables; - public List importedClasses; + public List importedClasses; public String pkg; @@ -67,7 +68,7 @@ public class ClassAVM2Item extends AVM2Item implements Block { return ret; } - public ClassAVM2Item(List importedClasses, String pkg, List openedNamespaces, int protectedNs, boolean isDynamic, boolean isFinal, int namespace, String className, GraphTargetItem extendsOp, List implementsOp, List staticInit, boolean staticInitActivation, List sinitVariables, GraphTargetItem constructor, List traits) { + public ClassAVM2Item(List importedClasses, String pkg, List openedNamespaces, int protectedNs, boolean isDynamic, boolean isFinal, int namespace, String className, GraphTargetItem extendsOp, List implementsOp, List staticInit, boolean staticInitActivation, List sinitVariables, GraphTargetItem constructor, List traits) { super(null, NOPRECEDENCE); this.importedClasses = importedClasses; this.pkg = pkg; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/InterfaceAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/InterfaceAVM2Item.java index a21b5cdcb..70d5625e4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/InterfaceAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/InterfaceAVM2Item.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; @@ -43,9 +44,9 @@ public class InterfaceAVM2Item extends AVM2Item { public String pkg; - public List importedClasses; + public List importedClasses; - public InterfaceAVM2Item(List importedClasses, String pkg, List openedNamespaces, boolean isFinal, int namespace, String name, List superInterfaces, List traits) { + public InterfaceAVM2Item(List importedClasses, String pkg, List openedNamespaces, boolean isFinal, int namespace, String name, List superInterfaces, List traits) { super(null, NOPRECEDENCE); this.importedClasses = importedClasses; this.pkg = pkg; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PackageAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PackageAVM2Item.java index 5a69d0668..65e16378d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PackageAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PackageAVM2Item.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; @@ -34,11 +35,11 @@ public class PackageAVM2Item extends AVM2Item { public String packageName; - public List importedClasses = new ArrayList<>(); + public List importedClasses = new ArrayList<>(); public int publicNs = 0; - public PackageAVM2Item(int publicNs, List importedClasses, String packageName, List items) { + public PackageAVM2Item(int publicNs, List importedClasses, String packageName, List items) { super(null, NOPRECEDENCE); this.publicNs = publicNs; this.importedClasses = importedClasses; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java index 9bff7d6f7..96c238524 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java @@ -44,6 +44,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.SourceGenerator; @@ -115,7 +116,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } return new ApplyTypeAVM2Item(null, obj, params); } else { - return new TypeItem(m.getNameWithNamespace(constants, true)); + return new TypeItem(m.getNameWithNamespace(constants)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java index 751600bb6..2eaf6af21 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; @@ -48,7 +49,7 @@ import java.util.List; */ public class UnresolvedAVM2Item extends AssignableAVM2Item { - private String name; + private DottedChain name; private int nsKind = -1; @@ -65,7 +66,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { private final boolean mustBeType; - public List importedClasses; + public List importedClasses; public List scopeStack = new ArrayList<>(); @@ -128,7 +129,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { */ public void appendName(String name) { - this.name += "." + name; + this.name.parts.add(name); } public void setDefinition(boolean definition) { @@ -150,15 +151,15 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { this.assignedValue = storeValue; } - public String getVariableName() { + public DottedChain getVariableName() { return name; } - public void setVariableName(String name) { + public void setVariableName(DottedChain name) { this.name = name; } - public UnresolvedAVM2Item(List subtypes, List importedClasses, boolean mustBeType, GraphTargetItem type, int line, String name, GraphTargetItem storeValue, List openedNamespaces) { + public UnresolvedAVM2Item(List subtypes, List importedClasses, boolean mustBeType, GraphTargetItem type, int line, DottedChain name, GraphTargetItem storeValue, List openedNamespaces) { super(storeValue); this.name = name; this.assignedValue = storeValue; @@ -264,7 +265,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { if (resolved != null) { return resolved.toString(); } - return name; + return name.toString(); } @Override @@ -290,14 +291,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } public GraphTargetItem resolve(GraphTargetItem thisType, List paramTypes, List paramNames, ABC abc, List otherAbcs, List callStack, List variables) throws CompilationException { - List parts = new ArrayList<>(); - if (name.contains(".")) { - String[] partsArr = name.split("\\."); - parts.addAll(Arrays.asList(partsArr)); - } else { - parts.add(name); - } - + List parts = name.parts; if (scopeStack.isEmpty()) { //Everything is multiname property in with command //search for variable @@ -326,13 +320,9 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } } //Search for types in imported classes - for (String imp : importedClasses) { - String impName = imp; - String impPkg = ""; - if (impName.contains(".")) { - impPkg = impName.substring(0, impName.lastIndexOf('.')); - impName = impName.substring(impName.lastIndexOf('.') + 1); - } + for (DottedChain imp : importedClasses) { + String impName = imp.getLast(); + if (impName.equals(parts.get(0))) { TypeItem ret = new TypeItem(imp); resolved = ret; @@ -354,13 +344,13 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { allAbcs.add(abc); allAbcs.addAll(otherAbcs); for (int i = 0; i < parts.size(); i++) { - String fname = Helper.joinStrings(parts.subList(0, i + 1), "."); + DottedChain fname = new DottedChain(parts.subList(0, i + 1)); //Helper.joinStrings(parts.subList(0, i + 1), "."); for (ABC a : allAbcs) { for (int c = 0; c < a.instance_info.size(); c++) { if (a.instance_info.get(c).deleted) { continue; } - if (a.instance_info.get(c).name_index > 0 && fname.equals(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants, true))) { + if (a.instance_info.get(c).name_index > 0 && fname.equals(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants))) { if (!subtypes.isEmpty() && parts.size() > i + 1) { continue; } @@ -400,7 +390,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { if (!subtypes.isEmpty() && parts.size() > 1) { continue; } - TypeItem ret = new TypeItem(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants, true)); + TypeItem ret = new TypeItem(a.instance_info.get(c).getName(a.constants).getNameWithNamespace(a.constants)); /*for (String s : subtypes) { UnresolvedAVM2Item su = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, true, null, line, s, null, openedNamespaces); su.resolve(thisType, paramTypes, paramNames, abc, otherAbcs, callStack, variables); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java index 241567799..21aa19a6b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java @@ -1,140 +1,140 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.types; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.List; - -public class InstanceInfo { - - public int name_index; - - public int super_index; - - public int flags; // 1 = sealed, 0 = dynamic, 2 = final, 4 = interface, 8 = ProtectedNs - - public int protectedNS; //if flags & 8 - - public int[] interfaces; - - public int iinit_index; // MethodInfo - constructor - - public Traits instance_traits; - - public static final int CLASS_SEALED = 1; //not dynamic - - public static final int CLASS_FINAL = 2; - - public static final int CLASS_INTERFACE = 4; - - public static final int CLASS_PROTECTEDNS = 8; - - @Internal - public boolean deleted; - - public InstanceInfo() { - instance_traits = new Traits(); - } - - public InstanceInfo(Traits traits) { - instance_traits = traits; - } - - @Override - public String toString() { - return "name_index=" + name_index + " super_index=" + super_index + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(); - } - - public String toString(ABC abc, List fullyQualifiedNames) { - String supIndexStr = "[nothing]"; - if (super_index > 0) { - supIndexStr = abc.constants.getMultiname(super_index).toString(abc.constants, fullyQualifiedNames); - } - return "name_index=" + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " super_index=" + supIndexStr + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(abc, fullyQualifiedNames); - } - - public GraphTextWriter getClassHeaderStr(GraphTextWriter writer, ABC abc, List fullyQualifiedNames, boolean allowPrivate) { - String modifiers; - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - modifiers = ns.getPrefix(abc); - if (!allowPrivate && modifiers.equals("private")) { - modifiers = ""; - } - if (!modifiers.isEmpty()) { - modifiers += " "; - } - - if (isFinal()) { - modifiers += "final "; - } - if (!isInterface() && isDynamic()) { - modifiers += "dynamic "; - } - String objType = "class "; - if (isInterface()) { - objType = "interface "; - } - - writer.appendNoHilight(modifiers + objType); - writer.hilightSpecial(abc.constants.getMultiname(name_index).getName(abc.constants, new ArrayList<>()/* No full names here*/, false), HighlightSpecialType.CLASS_NAME); - - if (super_index > 0) { - String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants, true); - writer.appendNoHilight(" extends "); - writer.hilightSpecial(abc.constants.getMultiname(super_index).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); - } - if (interfaces.length > 0) { - if (isInterface()) { - writer.appendNoHilight(" extends "); - } else { - writer.appendNoHilight(" implements "); - } - for (int i = 0; i < interfaces.length; i++) { - if (i > 0) { - writer.append(", "); - } - String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants, true); - writer.hilightSpecial(abc.constants.getMultiname(interfaces[i]).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); - } - } - - return writer; - } - - public Multiname getName(AVM2ConstantPool constants) { - return constants.getMultiname(name_index); - } - - public boolean isInterface() { - return ((flags & CLASS_INTERFACE) == CLASS_INTERFACE); - } - - public boolean isDynamic() { - return (flags & CLASS_SEALED) == 0; - } - - public boolean isFinal() { - return (flags & CLASS_FINAL) == CLASS_FINAL; - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.types; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.helpers.Helper; +import java.util.ArrayList; +import java.util.List; + +public class InstanceInfo { + + public int name_index; + + public int super_index; + + public int flags; // 1 = sealed, 0 = dynamic, 2 = final, 4 = interface, 8 = ProtectedNs + + public int protectedNS; //if flags & 8 + + public int[] interfaces; + + public int iinit_index; // MethodInfo - constructor + + public Traits instance_traits; + + public static final int CLASS_SEALED = 1; //not dynamic + + public static final int CLASS_FINAL = 2; + + public static final int CLASS_INTERFACE = 4; + + public static final int CLASS_PROTECTEDNS = 8; + + @Internal + public boolean deleted; + + public InstanceInfo() { + instance_traits = new Traits(); + } + + public InstanceInfo(Traits traits) { + instance_traits = traits; + } + + @Override + public String toString() { + return "name_index=" + name_index + " super_index=" + super_index + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(); + } + + public String toString(ABC abc, List fullyQualifiedNames) { + String supIndexStr = "[nothing]"; + if (super_index > 0) { + supIndexStr = abc.constants.getMultiname(super_index).toString(abc.constants, fullyQualifiedNames); + } + return "name_index=" + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " super_index=" + supIndexStr + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(abc, fullyQualifiedNames); + } + + public GraphTextWriter getClassHeaderStr(GraphTextWriter writer, ABC abc, List fullyQualifiedNames, boolean allowPrivate) { + String modifiers; + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + modifiers = ns.getPrefix(abc); + if (!allowPrivate && modifiers.equals("private")) { + modifiers = ""; + } + if (!modifiers.isEmpty()) { + modifiers += " "; + } + + if (isFinal()) { + modifiers += "final "; + } + if (!isInterface() && isDynamic()) { + modifiers += "dynamic "; + } + String objType = "class "; + if (isInterface()) { + objType = "interface "; + } + + writer.appendNoHilight(modifiers + objType); + writer.hilightSpecial(abc.constants.getMultiname(name_index).getName(abc.constants, new ArrayList()/* No full names here*/, false), HighlightSpecialType.CLASS_NAME); + + if (super_index > 0) { + String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants).toPrintableString(); + writer.appendNoHilight(" extends "); + writer.hilightSpecial(abc.constants.getMultiname(super_index).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); + } + if (interfaces.length > 0) { + if (isInterface()) { + writer.appendNoHilight(" extends "); + } else { + writer.appendNoHilight(" implements "); + } + for (int i = 0; i < interfaces.length; i++) { + if (i > 0) { + writer.append(", "); + } + String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants).toPrintableString(); + writer.hilightSpecial(abc.constants.getMultiname(interfaces[i]).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); + } + } + + return writer; + } + + public Multiname getName(AVM2ConstantPool constants) { + return constants.getMultiname(name_index); + } + + public boolean isInterface() { + return ((flags & CLASS_INTERFACE) == CLASS_INTERFACE); + } + + public boolean isDynamic() { + return (flags & CLASS_SEALED) == 0; + } + + public boolean isFinal() { + return (flags & CLASS_FINAL) == CLASS_FINAL; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java index 5452250a7..4003aa7a4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java @@ -310,7 +310,7 @@ public class MethodInfo { } String ptype = "*"; if (param_types[i] > 0) { - ptype = constants.getMultiname(param_types[i]).getNameWithNamespace(constants, false); + ptype = constants.getMultiname(param_types[i]).getNameWithNamespace(constants).toPrintableString(); } HighlightData pdata = new HighlightData(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java index f43b499d1..da15bae78 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java @@ -19,7 +19,9 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Helper; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -288,23 +290,28 @@ public class Multiname { } else { String name = constants.getString(name_index); if (fullyQualifiedNames != null && fullyQualifiedNames.contains(name)) { - return getNameWithNamespace(constants, raw); + DottedChain dc = getNameWithNamespace(constants); + return raw ? dc.toString() : dc.toPrintableString(); } return (isAttribute() ? "@" : "") + (raw ? name : IdentifiersDeobfuscation.printIdentifier(true, name)); } } - public String getNameWithNamespace(AVM2ConstantPool constants, boolean raw) { + public DottedChain getNameWithNamespace(AVM2ConstantPool constants) { StringBuilder ret = new StringBuilder(); Namespace ns = getNamespace(constants); + List chain = new ArrayList<>(); if (ns != null) { - String nsname = ns.getName(constants, raw); + String nsname = ns.getName(constants, true); if (nsname != null && !nsname.isEmpty()) { - ret.append(nsname).append("."); + String parts[] = nsname.split("\\."); + for (String p : parts) { + chain.add(p); + } } } - ret.append(getName(constants, null, raw)); - return ret.toString(); + chain.add(getName(constants, null, true)); + return new DottedChain(chain); } public Namespace getNamespace(AVM2ConstantPool constants) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java index 6a96ba792..42b6e7b63 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java @@ -88,6 +88,9 @@ public class ScriptInfo { } } } + if (ret.size() == 1) { + ret.get(0).isSimple = true; + } return ret; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index ccdf13ee7..d0de03bfb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -1,200 +1,200 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.types.traits; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.ClassPath; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.Namespace; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.NulWriter; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.helpers.Helper; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -public abstract class Trait implements Serializable { - - private static final int[] EMPTY_METADATA_ARRAY = new int[0]; - - public int name_index; - - public int kindType; - - public int kindFlags; - - public int[] metadata = EMPTY_METADATA_ARRAY; - - public long fileOffset; - - public byte[] bytes; - - public static final int ATTR_Final = 0x1; - - public static final int ATTR_Override = 0x2; - - public static final int ATTR_Metadata = 0x4; - - public static final int TRAIT_SLOT = 0; - - public static final int TRAIT_METHOD = 1; - - public static final int TRAIT_GETTER = 2; - - public static final int TRAIT_SETTER = 3; - - public static final int TRAIT_CLASS = 4; - - public static final int TRAIT_FUNCTION = 5; - - public static final int TRAIT_CONST = 6; - - public abstract void delete(ABC abc, boolean d); - - public String getModifiers(ABC abc, boolean isStatic) { - String ret = ""; - if ((kindFlags & ATTR_Override) > 0) { - ret += "override"; - } - Multiname m = getName(abc); - if (m != null) { - String nsname = ""; - //if (abc.constants.getNamespace(m.namespace_index).kind == Namespace.KIND_NAMESPACE) { - { - for (ABCContainerTag abcTag : abc.getAbcTags()) { - if (m.namespace_index == -1) { - break; - } - nsname = abcTag.getABC().nsValueToName(abc.constants.getNamespace(m.namespace_index).getName(abc.constants, true)); - if (nsname == null) { - break; - } - if (nsname.contains(".")) { - nsname = nsname.substring(nsname.lastIndexOf('.') + 1); - } - if (!nsname.isEmpty()) { - break; - } - } - } - Namespace ns = m.getNamespace(abc.constants); - - if (nsname.contains(":")) { - nsname = ""; - } - - if ((!nsname.isEmpty()) && (!nsname.equals("-"))) { - } else { - if (ns != null) { - if (ns.kind == Namespace.KIND_NAMESPACE) { - nsname = ns.getName(abc.constants, true); - } - } - } - - if (nsname != null && (!nsname.contains(":")) && (!nsname.isEmpty())) { - ret += " " + nsname; - } - if (ns != null) { - ret += " " + ns.getPrefix(abc); - } - } - if (isStatic) { - if ((this instanceof TraitSlotConst) && ((TraitSlotConst) this).isNamespace()) { - //static is automatic - } else { - ret += " static"; - } - } - if ((kindFlags & ATTR_Final) > 0) { - if (!isStatic) { - ret += " final"; - } - } - return ret.trim(); - } - - @Override - public String toString() { - return "name_index=" + name_index + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); - } - - public String toString(ABC abc, List fullyQualifiedNames) { - return abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); - } - - public GraphTextWriter toString(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - writer.appendNoHilight(abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata)); - return writer; - } - - public void convert(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - } - - public GraphTextWriter toStringPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - String nsname = ns.getName(abc.constants, false); - writer.appendNoHilight("package"); - if (!nsname.isEmpty()) { - writer.appendNoHilight(" " + nsname); //assume not null name - } - writer.startBlock(); - toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - writer.endBlock(); - writer.newLine(); - } - return writer; - } - - public void convertPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - String nsname = ns.getName(abc.constants, false); - convert(parent, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } - } - - public GraphTextWriter toStringHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - return writer; - } - - public void convertHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - convert(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } - - public Multiname getName(ABC abc) { - if (name_index == 0) { - return null; - } else { - return abc.constants.getMultiname(name_index); - } - } - - public abstract int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) throws InterruptedException; - - public ClassPath getPath(ABC abc) { - Multiname name = getName(abc); - Namespace ns = name.getNamespace(abc.constants); - String packageName = ns.getName(abc.constants, false); - String objectName = name.getName(abc.constants, new ArrayList<>(), false); - return new ClassPath(packageName, objectName); //assume not null name - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.types.traits; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ClassPath; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.helpers.Helper; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public abstract class Trait implements Serializable { + + private static final int[] EMPTY_METADATA_ARRAY = new int[0]; + + public int name_index; + + public int kindType; + + public int kindFlags; + + public int[] metadata = EMPTY_METADATA_ARRAY; + + public long fileOffset; + + public byte[] bytes; + + public static final int ATTR_Final = 0x1; + + public static final int ATTR_Override = 0x2; + + public static final int ATTR_Metadata = 0x4; + + public static final int TRAIT_SLOT = 0; + + public static final int TRAIT_METHOD = 1; + + public static final int TRAIT_GETTER = 2; + + public static final int TRAIT_SETTER = 3; + + public static final int TRAIT_CLASS = 4; + + public static final int TRAIT_FUNCTION = 5; + + public static final int TRAIT_CONST = 6; + + public abstract void delete(ABC abc, boolean d); + + public String getModifiers(ABC abc, boolean isStatic) { + String ret = ""; + if ((kindFlags & ATTR_Override) > 0) { + ret += "override"; + } + Multiname m = getName(abc); + if (m != null) { + String nsname = ""; + //if (abc.constants.getNamespace(m.namespace_index).kind == Namespace.KIND_NAMESPACE) { + { + for (ABCContainerTag abcTag : abc.getAbcTags()) { + if (m.namespace_index == -1) { + break; + } + nsname = abcTag.getABC().nsValueToName(abc.constants.getNamespace(m.namespace_index).getName(abc.constants, true)).toString(); + if (nsname == null) { + break; + } + if (nsname.contains(".")) { + nsname = nsname.substring(nsname.lastIndexOf('.') + 1); + } + if (!nsname.isEmpty()) { + break; + } + } + } + Namespace ns = m.getNamespace(abc.constants); + + if (nsname.contains(":")) { + nsname = ""; + } + + if ((!nsname.isEmpty()) && (!nsname.equals("-"))) { + } else { + if (ns != null) { + if (ns.kind == Namespace.KIND_NAMESPACE) { + nsname = ns.getName(abc.constants, true); + } + } + } + + if (nsname != null && (!nsname.contains(":")) && (!nsname.isEmpty())) { + ret += " " + nsname; + } + if (ns != null) { + ret += " " + ns.getPrefix(abc); + } + } + if (isStatic) { + if ((this instanceof TraitSlotConst) && ((TraitSlotConst) this).isNamespace()) { + //static is automatic + } else { + ret += " static"; + } + } + if ((kindFlags & ATTR_Final) > 0) { + if (!isStatic) { + ret += " final"; + } + } + return ret.trim(); + } + + @Override + public String toString() { + return "name_index=" + name_index + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); + } + + public String toString(ABC abc, List fullyQualifiedNames) { + return abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); + } + + public GraphTextWriter toString(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + writer.appendNoHilight(abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata)); + return writer; + } + + public void convert(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + } + + public GraphTextWriter toStringPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + String nsname = ns.getName(abc.constants, false); + writer.appendNoHilight("package"); + if (!nsname.isEmpty()) { + writer.appendNoHilight(" " + nsname); //assume not null name + } + writer.startBlock(); + toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + writer.endBlock(); + writer.newLine(); + } + return writer; + } + + public void convertPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + String nsname = ns.getName(abc.constants, false); + convert(parent, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } + } + + public GraphTextWriter toStringHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + return writer; + } + + public void convertHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + convert(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } + + public Multiname getName(ABC abc) { + if (name_index == 0) { + return null; + } else { + return abc.constants.getMultiname(name_index); + } + } + + public abstract int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) throws InterruptedException; + + public ClassPath getPath(ABC abc) { + Multiname name = getName(abc); + Namespace ns = name.getNamespace(abc.constants); + String packageName = ns.getName(abc.constants, false); + String objectName = name.getName(abc.constants, new ArrayList(), false); + return new ClassPath(packageName, objectName); //assume not null name + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index af40b017d..be97762cf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -37,6 +37,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.helpers.Helper; import java.util.ArrayList; @@ -90,57 +91,53 @@ public class TraitClass extends Trait implements TraitWithSlot { return "Class " + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " slot=" + slot_id + " class_info=" + class_info + " metadata=" + Helper.intArrToString(metadata); } - private boolean parseUsagesFromNS(ABC abc, List imports, List uses, int namespace_index, String ignorePackage, String name) { + private boolean parseUsagesFromNS(ABC abc, List imports, List uses, int namespace_index, String ignorePackage, String name) { Namespace ns = abc.constants.getNamespace(namespace_index); if (name.isEmpty()) { name = "*"; } - String newimport = ns.getName(abc.constants, ns.kind == Namespace.KIND_NAMESPACE); + String nsname = ns.getName(abc.constants, ns.kind == Namespace.KIND_NAMESPACE); + DottedChain newimport = nsname == null ? new DottedChain() : new DottedChain(nsname.split("\\.")); /*if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_NAMESPACE) && (ns.kind != Namespace.KIND_STATIC_PROTECTED)) { return false; }*/ /*if (ns.kind == Namespace.KIND_NAMESPACE)*/ { - String oldimport = newimport; - newimport = null; + DottedChain oldimport = newimport; + newimport = new DottedChain(); for (ABCContainerTag abcTag : abc.getAbcTags()) { - String newname = abcTag.getABC().nsValueToName(oldimport); - if (newname.equals("-")) { + DottedChain newname = abcTag.getABC().nsValueToName(oldimport == null ? null : oldimport.toString()); + if (newname.toString().equals("-")) { return true; } - if (!newname.isEmpty()) { + if (!newname.toString().isEmpty()) { newimport = newname; break; } } - if (newimport == null) { + if (newimport.parts.isEmpty()) { newimport = oldimport; - newimport += "." + name; + newimport.parts.add(name); } - if (newimport != null && newimport.isEmpty()) { - newimport = null; + if (!newimport.parts.isEmpty() && newimport.toString().isEmpty()) { + newimport.parts.clear(); } - if (newimport != null) { + if (newimport.parts.isEmpty()) { /* if(ns.kind==Namespace.KIND_PACKAGE){ newimport+=".*"; }*/ if (!imports.contains(newimport)) { - if (newimport.contains(":")) { - return true; - } - String pkg = ""; - if (newimport.contains(".")) { - pkg = newimport.substring(0, newimport.lastIndexOf('.')); - } - String usname = newimport; - if (usname.contains(".")) { - usname = usname.substring(usname.lastIndexOf('.') + 1); - } + //?? + /*if (newimport.contains(":")) { + return true; + }*/ + DottedChain pkg = newimport.getWithoutLast(); + String usname = newimport.getLast(); if (ns.kind == Namespace.KIND_PACKAGE) { if (!pkg.equals(ignorePackage)) { - if (!pkg.equals("__AS3__.vec")) { //Automatic import + if (!pkg.toString().equals("__AS3__.vec")) { //Automatic import imports.add(newimport); } } @@ -162,38 +159,39 @@ public class TraitClass extends Trait implements TraitWithSlot { return false; } - private void parseImportsUsagesFromNS(ABC abc, List imports, List uses, int namespace_index, String ignorePackage, String name) { + private void parseImportsUsagesFromNS(ABC abc, List imports, List uses, int namespace_index, String ignorePackage, String name) { Namespace ns = abc.constants.getNamespace(namespace_index); if (name.isEmpty()) { name = "*"; } - String newimport = ns.getName(abc.constants, false); + String niS = ns.getName(abc.constants, false); + DottedChain newimport = niS == null ? new DottedChain() : new DottedChain(niS.split("\\.")); if (parseUsagesFromNS(abc, imports, uses, namespace_index, ignorePackage, name)) { return; } else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { return; } - if (newimport == null) { - newimport = ""; - } - //if (!newimport.equals("")) { - newimport += "." + name; - if (newimport.contains(":")) { - return; + if (newimport.parts.isEmpty()) { + newimport = new DottedChain(""); } + newimport.parts.add(name); + //WUT? + /*if (newimport.contains(":")) { + return; + }*/ if (!imports.contains(newimport)) { - String pkg = newimport.substring(0, newimport.lastIndexOf('.')); - if (pkg.equals("__AS3__.vec")) { //special case - is imported always + DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.')); + if (pkg.toString().equals("__AS3__.vec")) { //special case - is imported always return; } - if (!pkg.equals(ignorePackage)) { + if (!pkg.toString().equals(ignorePackage)) { imports.add(newimport); } } //} } - private void parseUsagesFromMultiname(ABC abc, List imports, List uses, Multiname m, String ignorePackage, List fullyQualifiedNames) { + private void parseUsagesFromMultiname(ABC abc, List imports, List uses, Multiname m, String ignorePackage, List fullyQualifiedNames) { if (m != null) { if (m.kind == Multiname.TYPENAME) { if (m.qname_index != 0) { @@ -224,7 +222,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - private void parseImportsUsagesFromMultiname(ABC abc, List imports, List uses, Multiname m, String ignorePackage, List fullyQualifiedNames) { + private void parseImportsUsagesFromMultiname(ABC abc, List imports, List uses, Multiname m, String ignorePackage, List fullyQualifiedNames) { if (m != null) { if (m.kind == Multiname.TYPENAME) { if (m.qname_index != 0) { @@ -251,7 +249,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - private void parseImportsUsagesFromMethodInfo(ABC abc, int method_index, List imports, List uses, String ignorePackage, List fullyQualifiedNames, List visitedMethods) { + private void parseImportsUsagesFromMethodInfo(ABC abc, int method_index, List imports, List uses, String ignorePackage, List fullyQualifiedNames, List visitedMethods) { if ((method_index < 0) || (method_index >= abc.method_info.size())) { return; } @@ -272,7 +270,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } for (AVM2Instruction ins : body.getCode().code) { if (ins.definition instanceof AlchemyTypeIns) { - String nimport = AlchemyTypeIns.ALCHEMY_PACKAGE + "." + ins.definition.instructionName; + DottedChain nimport = new DottedChain((AlchemyTypeIns.ALCHEMY_PACKAGE + "." + ins.definition.instructionName).split("\\.")); if (!imports.contains(nimport)) { imports.add(nimport); } @@ -306,13 +304,13 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - private void parseImportsUsagesFromTraits(ABC abc, Traits ts, List imports, List uses, String ignorePackage, List fullyQualifiedNames) { + private void parseImportsUsagesFromTraits(ABC abc, Traits ts, List imports, List uses, String ignorePackage, List fullyQualifiedNames) { for (Trait t : ts.traits) { parseImportsUsagesFromTrait(abc, t, imports, uses, ignorePackage, fullyQualifiedNames); } } - private void parseImportsUsagesFromTrait(ABC abc, Trait t, List imports, List uses, String ignorePackage, List fullyQualifiedNames) { + private void parseImportsUsagesFromTrait(ABC abc, Trait t, List imports, List uses, String ignorePackage, List fullyQualifiedNames) { if (t instanceof TraitMethodGetterSetter) { TraitMethodGetterSetter tm = (TraitMethodGetterSetter) t; parseImportsUsagesFromMultiname(abc, imports, uses, abc.constants.getMultiname(tm.name_index), ignorePackage, fullyQualifiedNames); @@ -328,7 +326,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - private List getImportsUsages(ABC abc, List imports, List uses, List fullyQualifiedNames) { + private List getImportsUsages(ABC abc, List imports, List uses, List fullyQualifiedNames) { //constructor String packageName = abc.instance_info.get(class_info).getName(abc.constants).getNamespace(abc.constants).getName(abc.constants, false); //assume not null name @@ -384,7 +382,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } //imports - List imports = new ArrayList<>(); + List imports = new ArrayList<>(); List uses = new ArrayList<>(); getImportsUsages(abc, imports, uses, new ArrayList<>()); @@ -392,20 +390,16 @@ public class TraitClass extends Trait implements TraitWithSlot { List importnames = new ArrayList<>(); importnames.addAll(namesInThisPackage); - for (String ipath : imports) { - String name = ipath; - String pkg = ""; - if (name.contains(".")) { - pkg = name.substring(0, name.lastIndexOf('.')); - name = name.substring(name.lastIndexOf('.') + 1); - } - if (importnames.contains(name) || ((!pkg.isEmpty()) && isBuiltInClass(name))) { + for (DottedChain ipath : imports) { + String name = ipath.getLast(); + DottedChain pkg = ipath.getWithoutLast(); + if (importnames.contains(name) || ((!pkg.toString().isEmpty()) && isBuiltInClass(name))) { fullyQualifiedNames.add(name); } else { importnames.add(name); } } - /*List imports2 = new ArrayList<>(); + /*List imports2 = new ArrayList(); for (String path : imports) { String name = path; String pkg = ""; @@ -421,21 +415,23 @@ public class TraitClass extends Trait implements TraitWithSlot { imports = imports2;*/ for (int i = 0; i < imports.size(); i++) { - String imp = imports.get(i); - String pkg = imp.substring(0, imp.lastIndexOf('.')); - String name = imp.substring(imp.lastIndexOf('.') + 1); + DottedChain imp = imports.get(i); + DottedChain pkg = imp.getWithoutLast(); //imp.substring(0, imp.lastIndexOf('.')); + String name = imp.getLast();//imp.substring(imp.lastIndexOf('.') + 1); if (name.equals("*")) { continue; } - if (imports.contains(pkg + ".*")) { + DottedChain dAll = new DottedChain(pkg.parts); + dAll.parts.add("*"); + if (imports.contains(dAll)) { imports.remove(i); i--; } } boolean hasImport = false; - for (String imp : imports) { - if (!imp.startsWith(".")) { + for (DottedChain imp : imports) { + if (!imp.parts.get(0).isEmpty()) { //No imports from root package writer.appendNoHilight("import " + imp + ";").newLine(); hasImport = true; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ClassNameMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ClassNameMultinameUsage.java index a755f3e8e..56f98f9a9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ClassNameMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ClassNameMultinameUsage.java @@ -30,6 +30,6 @@ public class ClassNameMultinameUsage extends InsideClassMultinameUsage implement @Override public String toString() { - return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants, false); + return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants).toPrintableString(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/InsideClassMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/InsideClassMultinameUsage.java index ea1c31796..6244374aa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/InsideClassMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/InsideClassMultinameUsage.java @@ -36,7 +36,7 @@ public abstract class InsideClassMultinameUsage extends MultinameUsage { @Override public String toString() { - return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants, false); + return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants).toPrintableString(); } public int getMultinameIndex() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java new file mode 100644 index 000000000..b6066cc43 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph; + +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * + * @author JPEXS + */ +public class DottedChain { + + public List parts = new ArrayList<>(); + + public DottedChain(List parts) { + this.parts = new ArrayList<>(parts); + } + + public DottedChain(String... parts) { + for (int i = 0; i < parts.length; i++) { + this.parts.add(parts[i]); + } + } + + public String getLast() { + if (parts.isEmpty()) { + return ""; + } else { + return parts.get(parts.size() - 1); + } + } + + public DottedChain getWithoutLast() { + List nparts = new ArrayList<>(parts); + if (!nparts.isEmpty()) { + nparts.remove(nparts.size() - 1); + } + return new DottedChain(nparts); + } + + public String toPrintableString() { + String ret = ""; + for (int i = 0; i < parts.size(); i++) { + if (i > 0) { + ret += "."; + } + ret += IdentifiersDeobfuscation.printIdentifier(true, parts.get(0)); + } + return ret; + } + + @Override + public String toString() { + String ret = ""; + for (int i = 0; i < parts.size(); i++) { + if (i > 0) { + ret += "."; + } + ret += parts.get(i); + } + return ret; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 89 * hash + Objects.hashCode(this.parts); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof String) { + obj = new DottedChain(((String) obj).split("\\.")); + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final DottedChain other = (DottedChain) obj; + if (!Objects.equals(this.parts, other.parts)) { + return false; + } + return true; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java index ad27e56ea..9dc3bc898 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java @@ -31,33 +31,37 @@ import java.util.Objects; * @author JPEXS */ public class TypeItem extends GraphTargetItem { - + public static TypeItem BOOLEAN = new TypeItem("Boolean"); - + public static TypeItem STRING = new TypeItem("String"); - + public static TypeItem ARRAY = new TypeItem("Array"); - + public static UnboundedTypeItem UNBOUNDED = new UnboundedTypeItem(); - - public String fullTypeName; - - public TypeItem(String fullTypeName) { + + public DottedChain fullTypeName; + + public TypeItem(String s) { + this(s == null ? new DottedChain() : new DottedChain(s.split("\\."))); + } + + public TypeItem(DottedChain fullTypeName) { this(fullTypeName, new ArrayList()); } - - public TypeItem(String fullTypeName, List subtypes) { + + public TypeItem(DottedChain fullTypeName, List subtypes) { super(null, NOPRECEDENCE); this.fullTypeName = fullTypeName; } - + @Override public int hashCode() { int hash = 7; hash = 83 * hash + Objects.hashCode(this.fullTypeName); return hash; } - + @Override public boolean equals(Object obj) { if (obj == null) { @@ -72,37 +76,33 @@ public class TypeItem extends GraphTargetItem { } return true; } - + @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { if (localData.fullyQualifiedNames.contains(fullTypeName)) { - writer.hilightSpecial(IdentifiersDeobfuscation.printNamespace(localData.constantsAvm2 != null, fullTypeName), HighlightSpecialType.TYPE_NAME, fullTypeName); + writer.hilightSpecial(IdentifiersDeobfuscation.printNamespace(localData.constantsAvm2 != null, fullTypeName.toPrintableString()), HighlightSpecialType.TYPE_NAME, fullTypeName.toPrintableString()); } else { - String simpleName = fullTypeName; - if (simpleName.contains(".")) { - simpleName = simpleName.substring(simpleName.lastIndexOf('.') + 1); - } - writer.hilightSpecial(IdentifiersDeobfuscation.printNamespace(localData.constantsAvm2 != null, simpleName), HighlightSpecialType.TYPE_NAME, fullTypeName); + writer.hilightSpecial(IdentifiersDeobfuscation.printIdentifier(localData.constantsAvm2 != null, fullTypeName.getLast()), HighlightSpecialType.TYPE_NAME, fullTypeName.toPrintableString()); } - + return writer; } - + @Override public GraphTargetItem returnType() { return this; } - + @Override public boolean hasReturnValue() { return true; } - + @Override public String toString() { - return fullTypeName; + return fullTypeName.toString(); } - + @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return generator.generate(localData, this); diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/Helper.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/Helper.java index 5689b3a54..32be19f9d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/helpers/Helper.java +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/Helper.java @@ -1,1328 +1,1328 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.helpers; - -import com.jpexs.decompiler.flash.AppResources; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.helpers.Freed; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.Component; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.Area; -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferInt; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.xml.bind.DatatypeConverter; - -/** - * Class with helper method - * - * @author JPEXS, Paolo Cancedda - */ -public class Helper { - - public static String newLine = System.getProperty("line.separator"); - - public static String hexData = "#hexdata"; - - public static String constants = "#constants"; - - public static String decompilationErrorAdd = null; - - private static final Map shapeCache = new HashMap<>(); - - private static final String[] hexStringCache; - - static { - hexStringCache = new String[256]; - for (int i = 0; i < hexStringCache.length; i++) { - hexStringCache[i] = String.format("%02x", i); - } - } - - /** - * Converts array of int values to string - * - * @param array Array of int values - * @return String representation of the array - */ - public static String intArrToString(int[] array) { - StringBuilder sb = new StringBuilder(); - intArrToStringBuilder(array, sb); - return sb.toString(); - } - - public static void intArrToStringBuilder(int[] array, StringBuilder sb) { - sb.append("["); - for (int i = 0; i < array.length; i++) { - if (i > 0) { - sb.append(","); - } - sb.append(array[i]); - } - sb.append("]"); - } - - /** - * Converts array of byte values to string - * - * @param array Array of byte values - * @return String representation of the array - */ - public static String byteArrToString(byte[] array) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - for (int i = 0; i < array.length; i++) { - if (i > 0) { - sb.append(" "); - } - sb.append(hexStringCache[array[i] & 0xff]); - } - sb.append("]"); - return sb.toString(); - } - - /** - * Adds zeros to beginning of the number to fill specified length. Returns - * as string - * - * @param number Number as string - * @param length Length of new string - * @return Number with added zeros - */ - public static String padZeros(String number, int length) { - int count = length - number.length(); - for (int i = 0; i < count; i++) { - number = "0" + number; - } - return number; - } - - /** - * Formats specified address to four numbers xxxx - * (or five numbers when showing decimal addresses) - * - * @param number Address to format - * @return String representation of the address - */ - public static String formatAddress(long number) { - return formatAddress(number, Configuration.decimalAddress.get()); - } - - /** - * Formats specified address to four numbers xxxx - * (or five numbers when showing decimal addresses) - * - * @param number Address to format - * @param decimal Use decimal format - * @return String representation of the address - */ - public static String formatAddress(long number, boolean decimal) { - if (decimal) { - return String.format("%05d", number); - } - return String.format("%04x", number); - } - - /** - * Escapes string by adding backslashes - * - * @param s String to escape - * @return Escaped string - */ - public static String escapeString(String s) { - StringBuilder ret = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '\n') { - ret.append("\\n"); - } else if (c == '\r') { - ret.append("\\r"); - } else if (c == '\t') { - ret.append("\\t"); - } else if (c == '\b') { - ret.append("\\b"); - } else if (c == '\f') { - ret.append("\\f"); - } else if (c == '\\') { - ret.append("\\\\"); - } else if (c < 32) { - ret.append("\\x").append(byteToHex((byte) c)); - } else { - ret.append(c); - } - } - - return ret.toString(); - } - - /** - * Escapes string by adding backslashes - * - * @param s String to escape - * @return Escaped string - */ - public static String escapeActionScriptString(String s) { - StringBuilder ret = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '\n') { - ret.append("\\n"); - } else if (c == '\r') { - ret.append("\\r"); - } else if (c == '\t') { - ret.append("\\t"); - } else if (c == '\b') { - ret.append("\\b"); - } else if (c == '\f') { - ret.append("\\f"); - } else if (c == '\\') { - ret.append("\\\\"); - } else if (c == '"') { - ret.append("\\\""); - } else if (c == '\'') { - ret.append("\\'"); - } else if (c < 32) { - ret.append("\\x").append(byteToHex((byte) c)); - } else { - ret.append(c); - } - } - - return ret.toString(); - } - - /** - * Escapes string by adding backslashes - * - * @param s String to escape - * @return Escaped string - */ - public static String escapeJavaString(String s) { - StringBuilder ret = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '\n') { - ret.append("\\n"); - } else if (c == '\r') { - ret.append("\\r"); - } else if (c == '\t') { - ret.append("\\t"); - } else if (c == '\b') { - ret.append("\\b"); - } else if (c == '\f') { - ret.append("\\f"); - } else if (c == '\\') { - ret.append("\\\\"); - } else if (c == '"') { - ret.append("\\\""); - } else if (c < 32) { - // \\x is not available in Java string, we should use \\u instead - ret.append("\\u00").append(byteToHex((byte) c)); - } else { - ret.append(c); - } - } - - return ret.toString(); - } - - /** - * Unescapes a string that contains standard Java escape sequences. - *
    - *
  • \b \f \n \r \t \" \' : - * BS, FF, NL, CR, TAB, double and single quote.
  • - *
  • \X \XX \XXX : Octal character - * specification (0 - 377, 0x00 - 0xFF).
  • - *
  • \uXXXX : Hexadecimal based Unicode - * character.
  • - *
- * - * @param st - * A string optionally containing standard java escape sequences. - * @return The translated string. - */ - public static String unescapeJavaString(String st) { - - StringBuilder sb = new StringBuilder(st.length()); - - for (int i = 0; i < st.length(); i++) { - char ch = st.charAt(i); - if (ch == '\\') { - char nextChar = (i == st.length() - 1) ? '\\' : st - .charAt(i + 1); - // Octal escape? - if (nextChar >= '0' && nextChar <= '7') { - String code = "" + nextChar; - i++; - if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' - && st.charAt(i + 1) <= '7') { - code += st.charAt(i + 1); - i++; - if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' - && st.charAt(i + 1) <= '7') { - code += st.charAt(i + 1); - i++; - } - } - sb.append((char) Integer.parseInt(code, 8)); - continue; - } - - switch (nextChar) { - case '\\': - ch = '\\'; - break; - case 'b': - ch = '\b'; - break; - case 'f': - ch = '\f'; - break; - case 'n': - ch = '\n'; - break; - case 'r': - ch = '\r'; - break; - case 't': - ch = '\t'; - break; - case '\"': - ch = '\"'; - break; - case '\'': - ch = '\''; - break; - // Hex Unicode: u???? - case 'u': - if (i >= st.length() - 5) { - ch = 'u'; - break; - } - int code = Integer.parseInt( - "" + st.charAt(i + 2) + st.charAt(i + 3) - + st.charAt(i + 4) + st.charAt(i + 5), 16); - sb.append(Character.toChars(code)); - i += 5; - continue; - } - - i++; - } - - sb.append(ch); - } - - return sb.toString(); - } - - public static String getValidHtmlId(String text) { - // ID and NAME tokens must begin with a letter ([A-Za-z]) and - // may be followed by any number of letters, digits ([0-9]), - // hyphens ("-"), underscores ("_"), colons (":"), and periods ("."). - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if ((ch >= 'a' && ch <= 'z') - || (ch >= 'A' && ch <= 'Z') - || (i > 0 && ((ch >= '0' && ch <= '9') - || ch == '-' || ch == '_' || ch == ':' || ch == '.'))) { - sb.append(ch); - } else { - sb.append('_'); - } - } - return sb.toString(); - } - - private final static String SPACES12 = " "; - - private final static String ZEROS8 = "00000000"; - - public static String formatHex(int value, int width) { - StringBuilder sb = new StringBuilder(); - sb.append(Integer.toHexString(value)); - if (width > sb.length()) { - sb.insert(0, ZEROS8, 0, width - sb.length()); - } - return sb.toString(); - } - - public static String formatInt(int value, int width) { - StringBuilder sb = new StringBuilder(); - sb.append(value); - if (width > sb.length()) { - sb.insert(0, SPACES12, 0, width - sb.length()); - } - return sb.toString(); - } - - public static String indent(int level, String ss, String indentStr) { - StringBuilder sb = new StringBuilder(); - for (int ii = 0; ii < level; ii++) { - sb.append(indentStr); - } - sb.append(ss); - return sb.toString(); - } - - public static String indentRows(int level, String ss, String indentStr) { - StringBuilder sb = new StringBuilder(); - for (int ii = 0; ii < level; ii++) { - sb.append(indentStr); - } - ss = ss.replaceAll("(\r\n|\r|\n)", "\r\n"); - ss = "\r\n" + ss; - String repl = "\r\n" + sb.toString(); - ss = ss.replace("\r\n", repl); - if (ss.endsWith(repl)) { - ss = ss.substring(0, ss.length() - sb.toString().length()); - } - ss = ss.substring(2); - return ss; - } - - public static String unindentRows(int prefixLineCount, int level, String text) { - StringBuilder sb = new StringBuilder(); - Scanner scanner = new Scanner(text); - String indentStr = ""; - for (int i = 0; i < level; i++) { - indentStr += Configuration.getCodeFormatting().indentString; - } - int indentLength = indentStr.length(); - for (int i = 0; i < prefixLineCount; i++) { - scanner.nextLine(); // ignore line - } - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (line.startsWith(indentStr)) { - sb.append(line.substring(indentLength)).append(Configuration.getCodeFormatting().newLineChars); - } else { - return sb.toString(); - } - } - return sb.toString(); - } - - public static int getLineCount(String s) { - if (s.endsWith("\r\n")) { - s = s.substring(0, s.length() - 2); - } else if (s.endsWith("\r")) { - s = s.substring(0, s.length() - 1); - } else if (s.endsWith("\n")) { - s = s.substring(0, s.length() - 1); - } - String[] parts = s.split("(\r\n|\r|\n)"); - return parts.length; - } - - public static String padZeros(long number, int length) { - String ret = Long.toString(number); - while (ret.length() < length) { - ret = "0" + ret; - } - return ret; - } - - public static String byteToHex(byte b) { - return hexStringCache[b & 0xff]; - } - - public static String byteArrayToHex(byte[] data) { - StringBuilder sb = new StringBuilder(data.length * 2); - for (byte b : data) { - sb.append(hexStringCache[b & 0xff]); - } - - return sb.toString(); - } - - public static String bytesToHexString(byte[] bytes) { - return bytesToHexString(bytes, 0); - } - - public static String bytesToHexString(byte[] bytes, int start) { - StringBuilder sb = new StringBuilder(); - if (start < bytes.length) { - for (int ii = start; ii < bytes.length; ii++) { - sb.append(formatHex(bytes[ii] & 0xff, 2)); - sb.append(' '); - } - sb.setLength(sb.length() - 1); - } - return sb.toString(); - } - - public static String bytesToHexString(int maxByteCountInString, byte[] bytes, int start) { - if (bytes.length - start <= maxByteCountInString) { - return bytesToHexString(bytes, start); - } - byte[] trailingBytes = new byte[maxByteCountInString / 2]; - byte[] headingBytes = new byte[maxByteCountInString - trailingBytes.length]; - System.arraycopy(bytes, start, headingBytes, 0, headingBytes.length); - int startOfTrailingBytes = bytes.length - trailingBytes.length; - System.arraycopy(bytes, startOfTrailingBytes, trailingBytes, 0, trailingBytes.length); - StringBuilder sb = new StringBuilder(); - sb.append(bytesToHexString(headingBytes, 0)); - if (trailingBytes.length > 0) { - sb.append(" ... "); - sb.append(bytesToHexString(trailingBytes, 0)); - } - return sb.toString(); - } - - public static String format(String str, int len) { - if (len <= str.length()) { - return str; - } - StringBuilder sb = new StringBuilder(str); - for (int ii = str.length(); ii < len; ii++) { - sb.append(' '); - } - return sb.toString(); - } - - public static String joinStrings(Iterable arr, String glue) { - StringBuilder ret = new StringBuilder(); - boolean first = true; - for (Object s : arr) { - if (!first) { - ret.append(glue); - } else { - first = false; - } - ret.append(s); - } - return ret.toString(); - } - - public static String joinStrings(String[] arr, String glue) { - StringBuilder ret = new StringBuilder(); - boolean first = true; - for (String s : arr) { - if (!first) { - ret.append(glue); - } else { - first = false; - } - ret.append(s); - } - return ret.toString(); - } - - public static String joinStrings(List arr, String formatString, String glue) { - StringBuilder ret = new StringBuilder(); - boolean first = true; - for (String s : arr) { - if (!first) { - ret.append(glue); - } else { - first = false; - } - ret.append(String.format(formatString, s)); - } - return ret.toString(); - } - - public static String joinStrings(String[] arr, String formatString, String glue) { - StringBuilder ret = new StringBuilder(); - boolean first = true; - for (String s : arr) { - if (!first) { - ret.append(glue); - } else { - first = false; - } - ret.append(String.format(formatString, s)); - } - return ret.toString(); - } - - @SuppressWarnings("unchecked") - public static E deepCopy(E o) { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { - oos.writeObject(o); - oos.flush(); - } - E copy; - try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { - copy = (E) ois.readObject(); - } - return copy; - } catch (IOException | ClassNotFoundException ex) { - Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, "Copy error", ex); - return null; - } - } - - public static List toList(Object... rest) { - List ret = new ArrayList<>(); - ret.addAll(Arrays.asList(rest)); - return ret; - } - - public static ByteArrayInputStream getInputStream(byte[]... data) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - try { - for (byte[] d : data) { - baos.write(d); - } - } catch (IOException iex) { - } - return new ByteArrayInputStream(baos.toByteArray()); - } - - public static byte[] readFile(String... file) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - for (String f : file) { - try (FileInputStream fis = new FileInputStream(f)) { - byte[] buf = new byte[4096]; - int cnt = 0; - while ((cnt = fis.read(buf)) > 0) { - baos.write(buf, 0, cnt); - } - } catch (IOException ex) { - Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); - } - } - return baos.toByteArray(); - } - - public static String readTextFile(String... file) { - byte[] data = readFile(file); - if (data.length > 1 && data[0] == (byte) 0xef && data[1] == (byte) 0xbb && data[2] == (byte) 0xbf) { - // remove UTF-8 BOM - return new String(data, 3, data.length - 3, Utf8Helper.charset); - } - - return new String(data, Utf8Helper.charset); - } - - public static byte[] readStream(InputStream is) { - if (is instanceof MemoryInputStream) { - return ((MemoryInputStream) is).getAllRead(); - } - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - copyStream(is, baos, Long.MAX_VALUE); - return baos.toByteArray(); - } - - public static void copyStream(InputStream is, OutputStream os, long maxLength) { - try { - final int bufSize = 4096; - byte[] buf = new byte[bufSize]; - int cnt = 0; - while ((cnt = is.read(buf)) > 0) { - os.write(buf, 0, cnt); - maxLength -= cnt; - - // last chunk is smaller - if (maxLength < bufSize) { - buf = new byte[(int) maxLength]; - } - } - } catch (IOException ex) { - // ignore - } - } - - public static void writeFile(String file, byte[]... data) { - try (FileOutputStream fos = new FileOutputStream(file)) { - for (byte[] d : data) { - fos.write(d); - } - } catch (IOException ex) { - // ignore - } - } - - public static String stackToString(TranslateStack stack, LocalData localData) throws InterruptedException { - String ret = "["; - for (int i = stack.size() - 1; i >= 0; i--) { - if (i < stack.size() - 1) { - ret += ", "; - } - ret += stack.get(i).toString(localData); - } - ret += "]"; - return ret; - } - - public static File fixDialogFile(File f) { - Pattern pat = Pattern.compile("\"([^\"]+)\""); - String name = f.getAbsolutePath(); - Matcher m = pat.matcher(name); - if (m.find()) { - f = new File(m.group(1)); - } - return f; - } - - private static final BitSet fileNameInvalidChars; - - private static final List invalidFilenamesParts; - - static { - BitSet toEncode = new BitSet(256); - - for (int i = 0; i < 32; i++) { - toEncode.set(i); - } - - toEncode.set('\\'); - toEncode.set('/'); - toEncode.set(':'); - toEncode.set('*'); - toEncode.set('?'); - toEncode.set('"'); - toEncode.set('<'); - toEncode.set('>'); - toEncode.set('|'); - - fileNameInvalidChars = toEncode; - - //windows reserved filenames: - invalidFilenamesParts = new ArrayList<>(); - invalidFilenamesParts.add("CON"); - invalidFilenamesParts.add("PRN"); - invalidFilenamesParts.add("AUX"); - invalidFilenamesParts.add("CLOCK$"); - invalidFilenamesParts.add("NUL"); - for (int i = 1; i <= 9; i++) { - invalidFilenamesParts.add("COM" + i); - invalidFilenamesParts.add("LPT" + i); - } - } - - public static String makeFileName(String str) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < str.length(); i++) { - int ch = (int) str.charAt(i); - if (ch < 256 && fileNameInvalidChars.get(ch)) { - sb.append("%").append(String.format("%02X", ch)); - } else { - sb.append((char) ch); - } - } - str = sb.toString(); - if (str.endsWith(" ")) { - str = str.substring(0, str.length() - 1) + "%20"; - } - if (str.endsWith(".")) { - str = str.substring(0, str.length() - 1) + "%2E"; - } - str = "." + str + "."; - for (String inv : invalidFilenamesParts) { - str = Pattern.compile("\\." + Pattern.quote(inv) + "\\.", Pattern.CASE_INSENSITIVE).matcher(str).replaceAll("._" + inv + "."); - } - str = str.substring(1, str.length() - 1); //remove dots - if (str.isEmpty()) { - str = "unnamed"; - } - return str; - } - - public static String strToHex(String s) { - byte[] bs = Utf8Helper.getBytes(s); - String sn = ""; - for (int i = 0; i < bs.length; i++) { - sn += "0x" + Integer.toHexString(bs[i] & 0xff) + " "; - } - return sn; - } - - public static void emptyObject(Object obj) { - Field[] fields = obj.getClass().getDeclaredFields(); - for (Field f : fields) { - if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC - || f.getType().isPrimitive()) { - continue; - } - try { - f.setAccessible(true); - - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); - - Object v = f.get(obj); - if (v != null) { - try { - if (v instanceof Collection) { - ((Collection) v).clear(); - } - if (v instanceof Component) { - if (((Component) v).getParent() != null) { - ((Component) v).getParent().remove((Component) v); - } - } - if (v instanceof Freed) { - Freed freed = ((Freed) v); - if (!freed.isFreeing()) { - ((Freed) v).free(); - } - } - } catch (Throwable t) { - } - - f.set(obj, null); - } - } catch (UnsupportedOperationException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException ex) { - throw new Error(ex); - } - } - } - - public static String formatTimeSec(long timeMs) { - long timeS = timeMs / 1000; - timeMs %= 1000; - long timeM = timeS / 60; - timeS %= 60; - long timeH = timeM / 60; - timeM %= 60; - String timeStr = ""; - if (timeH > 0) { - timeStr += Helper.padZeros(timeH, 2) + ":"; - } - timeStr += Helper.padZeros(timeM, 2) + ":"; - timeStr += Helper.padZeros(timeS, 2) + "." + Helper.padZeros(timeMs, 3); - return timeStr; - } - - public static String formatFileSize(long fileSizeLong) { - double fileSize = fileSizeLong; - if (fileSize < 1024) { - return String.format("%d bytes", fileSizeLong); - } - fileSize /= 1024; - if (fileSize < 1024) { - return String.format("%.2f KB", fileSize); - } - fileSize /= 1024; - return String.format("%.2f MB", fileSize); - } - - public static void freeMem() { - Cache.clearAll(); - System.gc(); - } - - public static String formatTimeToText(int timeS) { - long timeM = timeS / 60; - timeS %= 60; - long timeH = timeM / 60; - timeM %= 60; - - String timeStr = ""; - String strAnd = AppResources.translate("timeFormat.and"); - String strHour = AppResources.translate("timeFormat.hour"); - String strHours = AppResources.translate("timeFormat.hours"); - String strMinute = AppResources.translate("timeFormat.minute"); - String strMinutes = AppResources.translate("timeFormat.minutes"); - String strSecond = AppResources.translate("timeFormat.second"); - String strSeconds = AppResources.translate("timeFormat.seconds"); - - if (timeH > 0) { - timeStr += timeH + " " + (timeH > 1 ? strHours : strHour); - } - if (timeM > 0) { - if (timeStr.length() > 0) { - timeStr += " " + strAnd + " "; - } - timeStr += timeM + " " + (timeM > 1 ? strMinutes : strMinute); - } - if (timeS > 0) { - if (timeStr.length() > 0) { - timeStr += " " + strAnd + " "; - } - timeStr += timeS + " " + (timeS > 1 ? strSeconds : strSecond); - } - - // (currently) used only in log, so no localization is required - return timeStr; - } - - public static GraphTextWriter byteArrayToHexWithHeader(GraphTextWriter writer, byte[] data) { - writer.appendNoHilight(hexData).newLine().newLine(); - return byteArrayToHex(writer, data, 8, 8, false, false); - } - - public static GraphTextWriter byteArrayToHex(GraphTextWriter writer, byte[] data, int bytesPerRow, int groupSize, boolean addChars, boolean showAddress) { - - /* // hex data from decompiled actions - Scanner scanner = new Scanner(srcWithHex); - while (scanner.hasNextLine()) { - String line = scanner.nextLine().trim(); - if (line.startsWith(";")) { - result.append(line.substring(1).trim()).append(nl); - } else { - result.append(";").append(line).append(nl); - } - }*/ - int length = data.length; - - int rowCount = length / bytesPerRow; - if (length % bytesPerRow > 0) { - rowCount++; - } - - long address = 0; - for (int row = 0; row < rowCount; row++) { - if (row > 0) { - writer.newLine(); - } - - if (showAddress) { - writer.appendNoHilight("0x" + String.format("%08x ", address)); - } - - for (int i = 0; i < bytesPerRow; i++) { - int idx = row * bytesPerRow + i; - if (length > idx) { - if (i > 0 && i % groupSize == 0) { - writer.appendNoHilight(" "); - } - writer.appendNoHilight(byteToHex(data[idx])).appendNoHilight(" "); - } else { - if (addChars) { - if (i > 0 && i % groupSize == 0) { - writer.appendNoHilight(" "); - } - writer.appendNoHilight(" "); - } - } - address += bytesPerRow; - } - - if (addChars) { - writer.appendNoHilight(" "); - for (int i = 0; i < bytesPerRow; i++) { - int idx = row * bytesPerRow + i; - if (length == idx) { - break; - } - if (i > 0 && i % groupSize == 0) { - writer.appendNoHilight(" "); - } - byte ch = data[idx]; - if (ch >= 0 && ch < 32) { - ch = '.'; - } - writer.appendNoHilight((char) ch + ""); - } - } - } - - writer.newLine(); - return writer; - } - - public static byte[] getBytesFromHexaText(String text) { - Scanner scanner = new Scanner(text); - scanner.nextLine(); // ignore first line - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - while (scanner.hasNextLine()) { - String line = scanner.nextLine().trim(); - if (line.startsWith(";")) { - continue; - } - line = line.replace(" ", ""); - for (int i = 0; i < line.length() / 2; i++) { - String hexStr = line.substring(i * 2, (i + 1) * 2); - byte b = (byte) Integer.parseInt(hexStr, 16); - baos.write(b); - } - } - byte[] data = baos.toByteArray(); - return data; - } - - public static List> getConstantPoolsFromText(String text) { - Scanner scanner = new Scanner(text); - scanner.nextLine(); // ignore first line - List> result = new ArrayList<>(); - List cPool = new ArrayList<>(); - result.add(cPool); - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (line.startsWith("---")) { - cPool = new ArrayList<>(); - result.add(cPool); - } - - String[] parts = line.split("\\|", 2); - if (parts.length >= 2) { - cPool.add(unescapeJavaString(parts[1])); - } - } - - return result; - } - - public static boolean contains(int[] array, int value) { - if (array == null) { - return false; - } - - for (int i : array) { - if (i == value) { - return true; - } - } - return false; - } - - public static void saveStream(InputStream is, File output) throws IOException { - byte[] buf = new byte[4096]; - int cnt; - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(output))) { - while ((cnt = is.read(buf)) > 0) { - fos.write(buf, 0, cnt); - fos.flush(); - } - } - } - - public static String getDecompilationSkippedComment() { - return "// " + AppResources.translate("decompilation.skipped"); - } - - public static void appendTimeoutComment(GraphTextWriter writer, int timeout) { - writer.appendNoHilight("/*").newLine(); - writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError")).newLine(); - writer.appendNoHilight(" * ").appendNoHilight(MessageFormat.format(AppResources.translate("decompilationError.timeout"), Helper.formatTimeToText(timeout))).newLine(); - writer.appendNoHilight(" */").newLine(); - writer.appendNoHilight("throw new flash.errors.IllegalOperationError(\""). - appendNoHilight(AppResources.translate("decompilationError.timeout.description")). - appendNoHilight("\");").newLine(); - } - - public static void appendErrorComment(GraphTextWriter writer, Throwable ex) { - writer.appendNoHilight("/*").newLine(); - writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError")).newLine(); - writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError.obfuscated")).newLine(); - if (decompilationErrorAdd != null) { - writer.appendNoHilight(" * ").appendNoHilight(decompilationErrorAdd).newLine(); - } - writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError.errorType")). - appendNoHilight(": " + ex.getClass().getSimpleName() + " (" + ex.getMessage() + ")").newLine(); - writer.appendNoHilight(" */").newLine(); - writer.appendNoHilight("throw new flash.errors.IllegalOperationError(\""). - appendNoHilight(AppResources.translate("decompilationError.error.description")). - appendNoHilight("\");").newLine(); - } - - public static String escapeHTML(String text) { - String[] from = new String[]{"&", "<", ">", "\"", "'", "/"}; - String[] to = new String[]{"&", "<", ">", """, "'", "/"}; - for (int i = 0; i < from.length; i++) { - text = text.replace(from[i], to[i]); - } - return text; - } - - public static String removeInvalidXMLCharacters(String text) { - StringBuilder sb = new StringBuilder(text.length()); - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if (ch > 31 || ch == 9 || ch == 10 || ch == 13) { - sb.append(ch); - } - } - - return sb.toString(); - } - - public static Shape imageToShapeOld(BufferedImage image) { - Area area = new Area(); - Rectangle rectangle = new Rectangle(); - int y1, y2; - int width = image.getWidth(); - int height = image.getHeight(); - - int[] imgData; - int type = image.getType(); - if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) { - imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); - } else { - imgData = image.getRGB(0, 0, width, height, null, 0, width); - } - - BitSet bs = new BitSet(width * height); - bs.set(type); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - int idx = width * y + x; - if ((imgData[idx] >>> 24) > 0) { - bs.set(idx); - } - } - } - - String key = byteArrayToBase64String(bs.toByteArray()); - if (shapeCache.containsKey(key)) { - return shapeCache.get(key); - } - - for (int x = 0; x < width; x++) { - y1 = Integer.MAX_VALUE; - y2 = -1; - for (int y = 0; y < height; y++) { - int rgb = imgData[width * y + x]; - rgb = rgb >>> 24; - if (rgb > 0) { - if (y1 == Integer.MAX_VALUE) { - y1 = y; - y2 = y; - } - if (y > (y2 + 1)) { - rectangle.setBounds(x, y1, 1, y2 - y1 + 1); - area.add(new Area(rectangle)); - y1 = y; - } - y2 = y; - } - } - if ((y2 - y1) >= 0) { - rectangle.setBounds(x, y1, 1, y2 - y1 + 1); - area.add(new Area(rectangle)); - } - } - - shapeCache.put(key, area); - return area; - } - - public static Shape imageToShape(BufferedImage image) { - Area area = new Area(); - int width = image.getWidth(); - int height = image.getHeight(); - - int[] imgData; - int type = image.getType(); - if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) { - imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); - } else { - imgData = image.getRGB(0, 0, width, height, null, 0, width); - } - - BitSet bs = new BitSet(width * height); - bs.set(type); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - int idx = width * y + x; - if ((imgData[idx] >>> 24) > 0) { - bs.set(idx); - } - } - } - - String key = byteArrayToBase64String(bs.toByteArray()); - if (shapeCache.containsKey(key)) { - return shapeCache.get(key); - } - - BitSet bsArea = new BitSet(width * height); - boolean modified = true; - - List leftCoordsX = new ArrayList<>(); - List leftCoordsY = new ArrayList<>(); - List rightCoordsX = new ArrayList<>(); - List rightCoordsY = new ArrayList<>(); - while (modified) { - modified = false; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int idx = width * y + x; - if ((imgData[idx] >>> 24) > 0 && !bsArea.get(idx)) { - leftCoordsX.clear(); - leftCoordsY.clear(); - rightCoordsX.clear(); - rightCoordsY.clear(); - int leftX = x; - int rightX = findRight(imgData, x, y, width); - leftCoordsX.add(leftX); - leftCoordsY.add(y); - rightCoordsX.add(rightX); - rightCoordsY.add(y); - setBitSet(bsArea, leftX, rightX, y, width); - int y2 = y + 1; - while (y2 < height) { - leftCoordsX.add(leftX); - leftCoordsY.add(y2); - rightCoordsX.add(rightX); - rightCoordsY.add(y2); - - int leftX2 = findFirst(imgData, leftX, rightX, y2, width); - if (leftX2 == -1) { - break; - } - - int rightX2 = findRight(imgData, leftX2, y2, width); - - if (leftX2 != leftX) { - leftCoordsX.add(leftX2); - leftCoordsY.add(y2); - } - - if (rightX2 != rightX) { - rightCoordsX.add(rightX2); - rightCoordsY.add(y2); - } - - leftX = leftX2; - rightX = rightX2; - - setBitSet(bsArea, leftX, rightX, y2, width); - y2++; - } - - int cnt = leftCoordsX.size() + rightCoordsX.size(); - int[] xCoords = new int[cnt]; - int[] yCoords = new int[cnt]; - for (int i = 0; i < rightCoordsX.size(); i++) { - xCoords[i] = rightCoordsX.get(i); - yCoords[i] = rightCoordsY.get(i); - } - - int offset = rightCoordsX.size(); - for (int i = 0; i < leftCoordsX.size(); i++) { - int idx2 = leftCoordsX.size() - i - 1; - xCoords[i + offset] = leftCoordsX.get(idx2); - yCoords[i + offset] = leftCoordsY.get(idx2); - } - - Area area2 = new Area(new Polygon(xCoords, yCoords, xCoords.length)); - area.add(area2); - modified = true; - } - } - } - } - - shapeCache.put(key, area); - return area; - } - - private static void setBitSet(BitSet bitSet, int x1, int x2, int y, int width) { - int idx = width * y + x1; - int idx2 = width * y + x2; - for (; idx < idx2; idx++) { - bitSet.set(idx); - } - } - - private static int findFirst(int[] imgData, int x1, int x2, int y, int width) { - int idx = width * y + x1; - if ((imgData[idx] >>> 24) > 0) { - while (x1 > 0 && (imgData[idx - 1] >>> 24) > 0) { - x1--; - idx--; - } - return x1; - } - - int idx2 = width * y + x2; - for (; idx < idx2; idx++) { - if ((imgData[idx] >>> 24) > 0) { - return x1; - } - - x1++; - } - - return -1; - } - - private static int findRight(int[] imgData, int x, int y, int width) { - int result = x; - int idx = width * y + x; - while (result < width && (imgData[idx] >>> 24) > 0) { - result++; - idx++; - } - - return result; - } - - public static void clearShapeCache() { - shapeCache.clear(); - } - - public static String byteArrayToBase64String(byte[] data) { - return DatatypeConverter.printBase64Binary(data); - } - - /** - * Formats double value (removes .0 from end) - * - * @param d - * @return String - */ - public static String doubleStr(double d) { - String ret = Double.toString(d); - if (ret.endsWith(".0")) { - ret = ret.substring(0, ret.length() - 2); - } - return ret; - } - - public static String byteCountStr(long bytes, boolean si) { - int unit = si ? 1000 : 1024; - if (bytes < unit) { - return bytes + " B"; - } - int exp = (int) (Math.log(bytes) / Math.log(unit)); - String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); - return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); - } -} +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.helpers; + +import com.jpexs.decompiler.flash.AppResources; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.helpers.Freed; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.awt.Component; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Scanner; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.xml.bind.DatatypeConverter; + +/** + * Class with helper method + * + * @author JPEXS, Paolo Cancedda + */ +public class Helper { + + public static String newLine = System.getProperty("line.separator"); + + public static String hexData = "#hexdata"; + + public static String constants = "#constants"; + + public static String decompilationErrorAdd = null; + + private static final Map shapeCache = new HashMap<>(); + + private static final String[] hexStringCache; + + static { + hexStringCache = new String[256]; + for (int i = 0; i < hexStringCache.length; i++) { + hexStringCache[i] = String.format("%02x", i); + } + } + + /** + * Converts array of int values to string + * + * @param array Array of int values + * @return String representation of the array + */ + public static String intArrToString(int[] array) { + StringBuilder sb = new StringBuilder(); + intArrToStringBuilder(array, sb); + return sb.toString(); + } + + public static void intArrToStringBuilder(int[] array, StringBuilder sb) { + sb.append("["); + for (int i = 0; i < array.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(array[i]); + } + sb.append("]"); + } + + /** + * Converts array of byte values to string + * + * @param array Array of byte values + * @return String representation of the array + */ + public static String byteArrToString(byte[] array) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < array.length; i++) { + if (i > 0) { + sb.append(" "); + } + sb.append(hexStringCache[array[i] & 0xff]); + } + sb.append("]"); + return sb.toString(); + } + + /** + * Adds zeros to beginning of the number to fill specified length. Returns + * as string + * + * @param number Number as string + * @param length Length of new string + * @return Number with added zeros + */ + public static String padZeros(String number, int length) { + int count = length - number.length(); + for (int i = 0; i < count; i++) { + number = "0" + number; + } + return number; + } + + /** + * Formats specified address to four numbers xxxx + * (or five numbers when showing decimal addresses) + * + * @param number Address to format + * @return String representation of the address + */ + public static String formatAddress(long number) { + return formatAddress(number, Configuration.decimalAddress.get()); + } + + /** + * Formats specified address to four numbers xxxx + * (or five numbers when showing decimal addresses) + * + * @param number Address to format + * @param decimal Use decimal format + * @return String representation of the address + */ + public static String formatAddress(long number, boolean decimal) { + if (decimal) { + return String.format("%05d", number); + } + return String.format("%04x", number); + } + + /** + * Escapes string by adding backslashes + * + * @param s String to escape + * @return Escaped string + */ + public static String escapeString(String s) { + StringBuilder ret = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '\n') { + ret.append("\\n"); + } else if (c == '\r') { + ret.append("\\r"); + } else if (c == '\t') { + ret.append("\\t"); + } else if (c == '\b') { + ret.append("\\b"); + } else if (c == '\f') { + ret.append("\\f"); + } else if (c == '\\') { + ret.append("\\\\"); + } else if (c < 32) { + ret.append("\\x").append(byteToHex((byte) c)); + } else { + ret.append(c); + } + } + + return ret.toString(); + } + + /** + * Escapes string by adding backslashes + * + * @param s String to escape + * @return Escaped string + */ + public static String escapeActionScriptString(String s) { + StringBuilder ret = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '\n') { + ret.append("\\n"); + } else if (c == '\r') { + ret.append("\\r"); + } else if (c == '\t') { + ret.append("\\t"); + } else if (c == '\b') { + ret.append("\\b"); + } else if (c == '\f') { + ret.append("\\f"); + } else if (c == '\\') { + ret.append("\\\\"); + } else if (c == '"') { + ret.append("\\\""); + } else if (c == '\'') { + ret.append("\\'"); + } else if (c < 32) { + ret.append("\\x").append(byteToHex((byte) c)); + } else { + ret.append(c); + } + } + + return ret.toString(); + } + + /** + * Escapes string by adding backslashes + * + * @param s String to escape + * @return Escaped string + */ + public static String escapeJavaString(String s) { + StringBuilder ret = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '\n') { + ret.append("\\n"); + } else if (c == '\r') { + ret.append("\\r"); + } else if (c == '\t') { + ret.append("\\t"); + } else if (c == '\b') { + ret.append("\\b"); + } else if (c == '\f') { + ret.append("\\f"); + } else if (c == '\\') { + ret.append("\\\\"); + } else if (c == '"') { + ret.append("\\\""); + } else if (c < 32) { + // \\x is not available in Java string, we should use \\u instead + ret.append("\\u00").append(byteToHex((byte) c)); + } else { + ret.append(c); + } + } + + return ret.toString(); + } + + /** + * Unescapes a string that contains standard Java escape sequences. + *
    + *
  • \b \f \n \r \t \" \' : + * BS, FF, NL, CR, TAB, double and single quote.
  • + *
  • \X \XX \XXX : Octal character + * specification (0 - 377, 0x00 - 0xFF).
  • + *
  • \uXXXX : Hexadecimal based Unicode + * character.
  • + *
+ * + * @param st + * A string optionally containing standard java escape sequences. + * @return The translated string. + */ + public static String unescapeJavaString(String st) { + + StringBuilder sb = new StringBuilder(st.length()); + + for (int i = 0; i < st.length(); i++) { + char ch = st.charAt(i); + if (ch == '\\') { + char nextChar = (i == st.length() - 1) ? '\\' : st + .charAt(i + 1); + // Octal escape? + if (nextChar >= '0' && nextChar <= '7') { + String code = "" + nextChar; + i++; + if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' + && st.charAt(i + 1) <= '7') { + code += st.charAt(i + 1); + i++; + if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' + && st.charAt(i + 1) <= '7') { + code += st.charAt(i + 1); + i++; + } + } + sb.append((char) Integer.parseInt(code, 8)); + continue; + } + + switch (nextChar) { + case '\\': + ch = '\\'; + break; + case 'b': + ch = '\b'; + break; + case 'f': + ch = '\f'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + case '\"': + ch = '\"'; + break; + case '\'': + ch = '\''; + break; + // Hex Unicode: u???? + case 'u': + if (i >= st.length() - 5) { + ch = 'u'; + break; + } + int code = Integer.parseInt( + "" + st.charAt(i + 2) + st.charAt(i + 3) + + st.charAt(i + 4) + st.charAt(i + 5), 16); + sb.append(Character.toChars(code)); + i += 5; + continue; + } + + i++; + } + + sb.append(ch); + } + + return sb.toString(); + } + + public static String getValidHtmlId(String text) { + // ID and NAME tokens must begin with a letter ([A-Za-z]) and + // may be followed by any number of letters, digits ([0-9]), + // hyphens ("-"), underscores ("_"), colons (":"), and periods ("."). + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if ((ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (i > 0 && ((ch >= '0' && ch <= '9') + || ch == '-' || ch == '_' || ch == ':' || ch == '.'))) { + sb.append(ch); + } else { + sb.append('_'); + } + } + return sb.toString(); + } + + private final static String SPACES12 = " "; + + private final static String ZEROS8 = "00000000"; + + public static String formatHex(int value, int width) { + StringBuilder sb = new StringBuilder(); + sb.append(Integer.toHexString(value)); + if (width > sb.length()) { + sb.insert(0, ZEROS8, 0, width - sb.length()); + } + return sb.toString(); + } + + public static String formatInt(int value, int width) { + StringBuilder sb = new StringBuilder(); + sb.append(value); + if (width > sb.length()) { + sb.insert(0, SPACES12, 0, width - sb.length()); + } + return sb.toString(); + } + + public static String indent(int level, String ss, String indentStr) { + StringBuilder sb = new StringBuilder(); + for (int ii = 0; ii < level; ii++) { + sb.append(indentStr); + } + sb.append(ss); + return sb.toString(); + } + + public static String indentRows(int level, String ss, String indentStr) { + StringBuilder sb = new StringBuilder(); + for (int ii = 0; ii < level; ii++) { + sb.append(indentStr); + } + ss = ss.replaceAll("(\r\n|\r|\n)", "\r\n"); + ss = "\r\n" + ss; + String repl = "\r\n" + sb.toString(); + ss = ss.replace("\r\n", repl); + if (ss.endsWith(repl)) { + ss = ss.substring(0, ss.length() - sb.toString().length()); + } + ss = ss.substring(2); + return ss; + } + + public static String unindentRows(int prefixLineCount, int level, String text) { + StringBuilder sb = new StringBuilder(); + Scanner scanner = new Scanner(text); + String indentStr = ""; + for (int i = 0; i < level; i++) { + indentStr += Configuration.getCodeFormatting().indentString; + } + int indentLength = indentStr.length(); + for (int i = 0; i < prefixLineCount; i++) { + scanner.nextLine(); // ignore line + } + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.startsWith(indentStr)) { + sb.append(line.substring(indentLength)).append(Configuration.getCodeFormatting().newLineChars); + } else { + return sb.toString(); + } + } + return sb.toString(); + } + + public static int getLineCount(String s) { + if (s.endsWith("\r\n")) { + s = s.substring(0, s.length() - 2); + } else if (s.endsWith("\r")) { + s = s.substring(0, s.length() - 1); + } else if (s.endsWith("\n")) { + s = s.substring(0, s.length() - 1); + } + String[] parts = s.split("(\r\n|\r|\n)"); + return parts.length; + } + + public static String padZeros(long number, int length) { + String ret = Long.toString(number); + while (ret.length() < length) { + ret = "0" + ret; + } + return ret; + } + + public static String byteToHex(byte b) { + return hexStringCache[b & 0xff]; + } + + public static String byteArrayToHex(byte[] data) { + StringBuilder sb = new StringBuilder(data.length * 2); + for (byte b : data) { + sb.append(hexStringCache[b & 0xff]); + } + + return sb.toString(); + } + + public static String bytesToHexString(byte[] bytes) { + return bytesToHexString(bytes, 0); + } + + public static String bytesToHexString(byte[] bytes, int start) { + StringBuilder sb = new StringBuilder(); + if (start < bytes.length) { + for (int ii = start; ii < bytes.length; ii++) { + sb.append(formatHex(bytes[ii] & 0xff, 2)); + sb.append(' '); + } + sb.setLength(sb.length() - 1); + } + return sb.toString(); + } + + public static String bytesToHexString(int maxByteCountInString, byte[] bytes, int start) { + if (bytes.length - start <= maxByteCountInString) { + return bytesToHexString(bytes, start); + } + byte[] trailingBytes = new byte[maxByteCountInString / 2]; + byte[] headingBytes = new byte[maxByteCountInString - trailingBytes.length]; + System.arraycopy(bytes, start, headingBytes, 0, headingBytes.length); + int startOfTrailingBytes = bytes.length - trailingBytes.length; + System.arraycopy(bytes, startOfTrailingBytes, trailingBytes, 0, trailingBytes.length); + StringBuilder sb = new StringBuilder(); + sb.append(bytesToHexString(headingBytes, 0)); + if (trailingBytes.length > 0) { + sb.append(" ... "); + sb.append(bytesToHexString(trailingBytes, 0)); + } + return sb.toString(); + } + + public static String format(String str, int len) { + if (len <= str.length()) { + return str; + } + StringBuilder sb = new StringBuilder(str); + for (int ii = str.length(); ii < len; ii++) { + sb.append(' '); + } + return sb.toString(); + } + + public static String joinStrings(Iterable arr, String glue) { + StringBuilder ret = new StringBuilder(); + boolean first = true; + for (Object s : arr) { + if (!first) { + ret.append(glue); + } else { + first = false; + } + ret.append(s); + } + return ret.toString(); + } + + public static String joinStrings(String[] arr, String glue) { + StringBuilder ret = new StringBuilder(); + boolean first = true; + for (String s : arr) { + if (!first) { + ret.append(glue); + } else { + first = false; + } + ret.append(s); + } + return ret.toString(); + } + + public static String joinStrings(List arr, String formatString, String glue) { + StringBuilder ret = new StringBuilder(); + boolean first = true; + for (String s : arr) { + if (!first) { + ret.append(glue); + } else { + first = false; + } + ret.append(String.format(formatString, s)); + } + return ret.toString(); + } + + public static String joinStrings(String[] arr, String formatString, String glue) { + StringBuilder ret = new StringBuilder(); + boolean first = true; + for (String s : arr) { + if (!first) { + ret.append(glue); + } else { + first = false; + } + ret.append(String.format(formatString, s)); + } + return ret.toString(); + } + + @SuppressWarnings("unchecked") + public static E deepCopy(E o) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(o); + oos.flush(); + } + E copy; + try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + copy = (E) ois.readObject(); + } + return copy; + } catch (IOException | ClassNotFoundException ex) { + Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, "Copy error", ex); + return null; + } + } + + public static List toList(Object... rest) { + List ret = new ArrayList<>(); + ret.addAll(Arrays.asList(rest)); + return ret; + } + + public static ByteArrayInputStream getInputStream(byte[]... data) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + try { + for (byte[] d : data) { + baos.write(d); + } + } catch (IOException iex) { + } + return new ByteArrayInputStream(baos.toByteArray()); + } + + public static byte[] readFile(String... file) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (String f : file) { + try (FileInputStream fis = new FileInputStream(f)) { + byte[] buf = new byte[4096]; + int cnt = 0; + while ((cnt = fis.read(buf)) > 0) { + baos.write(buf, 0, cnt); + } + } catch (IOException ex) { + Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); + } + } + return baos.toByteArray(); + } + + public static String readTextFile(String... file) { + byte[] data = readFile(file); + if (data.length > 1 && data[0] == (byte) 0xef && data[1] == (byte) 0xbb && data[2] == (byte) 0xbf) { + // remove UTF-8 BOM + return new String(data, 3, data.length - 3, Utf8Helper.charset); + } + + return new String(data, Utf8Helper.charset); + } + + public static byte[] readStream(InputStream is) { + if (is instanceof MemoryInputStream) { + return ((MemoryInputStream) is).getAllRead(); + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copyStream(is, baos, Long.MAX_VALUE); + return baos.toByteArray(); + } + + public static void copyStream(InputStream is, OutputStream os, long maxLength) { + try { + final int bufSize = 4096; + byte[] buf = new byte[bufSize]; + int cnt = 0; + while ((cnt = is.read(buf)) > 0) { + os.write(buf, 0, cnt); + maxLength -= cnt; + + // last chunk is smaller + if (maxLength < bufSize) { + buf = new byte[(int) maxLength]; + } + } + } catch (IOException ex) { + // ignore + } + } + + public static void writeFile(String file, byte[]... data) { + try (FileOutputStream fos = new FileOutputStream(file)) { + for (byte[] d : data) { + fos.write(d); + } + } catch (IOException ex) { + // ignore + } + } + + public static String stackToString(TranslateStack stack, LocalData localData) throws InterruptedException { + String ret = "["; + for (int i = stack.size() - 1; i >= 0; i--) { + if (i < stack.size() - 1) { + ret += ", "; + } + ret += stack.get(i).toString(localData); + } + ret += "]"; + return ret; + } + + public static File fixDialogFile(File f) { + Pattern pat = Pattern.compile("\"([^\"]+)\""); + String name = f.getAbsolutePath(); + Matcher m = pat.matcher(name); + if (m.find()) { + f = new File(m.group(1)); + } + return f; + } + + private static final BitSet fileNameInvalidChars; + + private static final List invalidFilenamesParts; + + static { + BitSet toEncode = new BitSet(256); + + for (int i = 0; i < 32; i++) { + toEncode.set(i); + } + + toEncode.set('\\'); + toEncode.set('/'); + toEncode.set(':'); + toEncode.set('*'); + toEncode.set('?'); + toEncode.set('"'); + toEncode.set('<'); + toEncode.set('>'); + toEncode.set('|'); + + fileNameInvalidChars = toEncode; + + //windows reserved filenames: + invalidFilenamesParts = new ArrayList<>(); + invalidFilenamesParts.add("CON"); + invalidFilenamesParts.add("PRN"); + invalidFilenamesParts.add("AUX"); + invalidFilenamesParts.add("CLOCK$"); + invalidFilenamesParts.add("NUL"); + for (int i = 1; i <= 9; i++) { + invalidFilenamesParts.add("COM" + i); + invalidFilenamesParts.add("LPT" + i); + } + } + + public static String makeFileName(String str) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + int ch = (int) str.charAt(i); + if (ch < 256 && fileNameInvalidChars.get(ch)) { + sb.append("%").append(String.format("%02X", ch)); + } else { + sb.append((char) ch); + } + } + str = sb.toString(); + if (str.endsWith(" ")) { + str = str.substring(0, str.length() - 1) + "%20"; + } + if (str.endsWith(".")) { + str = str.substring(0, str.length() - 1) + "%2E"; + } + str = "." + str + "."; + for (String inv : invalidFilenamesParts) { + str = Pattern.compile("\\." + Pattern.quote(inv) + "\\.", Pattern.CASE_INSENSITIVE).matcher(str).replaceAll("._" + inv + "."); + } + str = str.substring(1, str.length() - 1); //remove dots + if (str.isEmpty()) { + str = "unnamed"; + } + return str; + } + + public static String strToHex(String s) { + byte[] bs = Utf8Helper.getBytes(s); + String sn = ""; + for (int i = 0; i < bs.length; i++) { + sn += "0x" + Integer.toHexString(bs[i] & 0xff) + " "; + } + return sn; + } + + public static void emptyObject(Object obj) { + Field[] fields = obj.getClass().getDeclaredFields(); + for (Field f : fields) { + if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC + || f.getType().isPrimitive()) { + continue; + } + try { + f.setAccessible(true); + + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); + + Object v = f.get(obj); + if (v != null) { + try { + if (v instanceof Collection) { + ((Collection) v).clear(); + } + if (v instanceof Component) { + if (((Component) v).getParent() != null) { + ((Component) v).getParent().remove((Component) v); + } + } + if (v instanceof Freed) { + Freed freed = ((Freed) v); + if (!freed.isFreeing()) { + ((Freed) v).free(); + } + } + } catch (Throwable t) { + } + + f.set(obj, null); + } + } catch (UnsupportedOperationException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException ex) { + throw new Error(ex); + } + } + } + + public static String formatTimeSec(long timeMs) { + long timeS = timeMs / 1000; + timeMs %= 1000; + long timeM = timeS / 60; + timeS %= 60; + long timeH = timeM / 60; + timeM %= 60; + String timeStr = ""; + if (timeH > 0) { + timeStr += Helper.padZeros(timeH, 2) + ":"; + } + timeStr += Helper.padZeros(timeM, 2) + ":"; + timeStr += Helper.padZeros(timeS, 2) + "." + Helper.padZeros(timeMs, 3); + return timeStr; + } + + public static String formatFileSize(long fileSizeLong) { + double fileSize = fileSizeLong; + if (fileSize < 1024) { + return String.format("%d bytes", fileSizeLong); + } + fileSize /= 1024; + if (fileSize < 1024) { + return String.format("%.2f KB", fileSize); + } + fileSize /= 1024; + return String.format("%.2f MB", fileSize); + } + + public static void freeMem() { + Cache.clearAll(); + System.gc(); + } + + public static String formatTimeToText(int timeS) { + long timeM = timeS / 60; + timeS %= 60; + long timeH = timeM / 60; + timeM %= 60; + + String timeStr = ""; + String strAnd = AppResources.translate("timeFormat.and"); + String strHour = AppResources.translate("timeFormat.hour"); + String strHours = AppResources.translate("timeFormat.hours"); + String strMinute = AppResources.translate("timeFormat.minute"); + String strMinutes = AppResources.translate("timeFormat.minutes"); + String strSecond = AppResources.translate("timeFormat.second"); + String strSeconds = AppResources.translate("timeFormat.seconds"); + + if (timeH > 0) { + timeStr += timeH + " " + (timeH > 1 ? strHours : strHour); + } + if (timeM > 0) { + if (timeStr.length() > 0) { + timeStr += " " + strAnd + " "; + } + timeStr += timeM + " " + (timeM > 1 ? strMinutes : strMinute); + } + if (timeS > 0) { + if (timeStr.length() > 0) { + timeStr += " " + strAnd + " "; + } + timeStr += timeS + " " + (timeS > 1 ? strSeconds : strSecond); + } + + // (currently) used only in log, so no localization is required + return timeStr; + } + + public static GraphTextWriter byteArrayToHexWithHeader(GraphTextWriter writer, byte[] data) { + writer.appendNoHilight(hexData).newLine().newLine(); + return byteArrayToHex(writer, data, 8, 8, false, false); + } + + public static GraphTextWriter byteArrayToHex(GraphTextWriter writer, byte[] data, int bytesPerRow, int groupSize, boolean addChars, boolean showAddress) { + + /* // hex data from decompiled actions + Scanner scanner = new Scanner(srcWithHex); + while (scanner.hasNextLine()) { + String line = scanner.nextLine().trim(); + if (line.startsWith(";")) { + result.append(line.substring(1).trim()).append(nl); + } else { + result.append(";").append(line).append(nl); + } + }*/ + int length = data.length; + + int rowCount = length / bytesPerRow; + if (length % bytesPerRow > 0) { + rowCount++; + } + + long address = 0; + for (int row = 0; row < rowCount; row++) { + if (row > 0) { + writer.newLine(); + } + + if (showAddress) { + writer.appendNoHilight("0x" + String.format("%08x ", address)); + } + + for (int i = 0; i < bytesPerRow; i++) { + int idx = row * bytesPerRow + i; + if (length > idx) { + if (i > 0 && i % groupSize == 0) { + writer.appendNoHilight(" "); + } + writer.appendNoHilight(byteToHex(data[idx])).appendNoHilight(" "); + } else { + if (addChars) { + if (i > 0 && i % groupSize == 0) { + writer.appendNoHilight(" "); + } + writer.appendNoHilight(" "); + } + } + address += bytesPerRow; + } + + if (addChars) { + writer.appendNoHilight(" "); + for (int i = 0; i < bytesPerRow; i++) { + int idx = row * bytesPerRow + i; + if (length == idx) { + break; + } + if (i > 0 && i % groupSize == 0) { + writer.appendNoHilight(" "); + } + byte ch = data[idx]; + if (ch >= 0 && ch < 32) { + ch = '.'; + } + writer.appendNoHilight((char) ch + ""); + } + } + } + + writer.newLine(); + return writer; + } + + public static byte[] getBytesFromHexaText(String text) { + Scanner scanner = new Scanner(text); + scanner.nextLine(); // ignore first line + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + while (scanner.hasNextLine()) { + String line = scanner.nextLine().trim(); + if (line.startsWith(";")) { + continue; + } + line = line.replace(" ", ""); + for (int i = 0; i < line.length() / 2; i++) { + String hexStr = line.substring(i * 2, (i + 1) * 2); + byte b = (byte) Integer.parseInt(hexStr, 16); + baos.write(b); + } + } + byte[] data = baos.toByteArray(); + return data; + } + + public static List> getConstantPoolsFromText(String text) { + Scanner scanner = new Scanner(text); + scanner.nextLine(); // ignore first line + List> result = new ArrayList<>(); + List cPool = new ArrayList<>(); + result.add(cPool); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.startsWith("---")) { + cPool = new ArrayList<>(); + result.add(cPool); + } + + String[] parts = line.split("\\|", 2); + if (parts.length >= 2) { + cPool.add(unescapeJavaString(parts[1])); + } + } + + return result; + } + + public static boolean contains(int[] array, int value) { + if (array == null) { + return false; + } + + for (int i : array) { + if (i == value) { + return true; + } + } + return false; + } + + public static void saveStream(InputStream is, File output) throws IOException { + byte[] buf = new byte[4096]; + int cnt; + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(output))) { + while ((cnt = is.read(buf)) > 0) { + fos.write(buf, 0, cnt); + fos.flush(); + } + } + } + + public static String getDecompilationSkippedComment() { + return "// " + AppResources.translate("decompilation.skipped"); + } + + public static void appendTimeoutComment(GraphTextWriter writer, int timeout) { + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError")).newLine(); + writer.appendNoHilight(" * ").appendNoHilight(MessageFormat.format(AppResources.translate("decompilationError.timeout"), Helper.formatTimeToText(timeout))).newLine(); + writer.appendNoHilight(" */").newLine(); + writer.appendNoHilight("throw new flash.errors.IllegalOperationError(\""). + appendNoHilight(AppResources.translate("decompilationError.timeout.description")). + appendNoHilight("\");").newLine(); + } + + public static void appendErrorComment(GraphTextWriter writer, Throwable ex) { + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError")).newLine(); + writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError.obfuscated")).newLine(); + if (decompilationErrorAdd != null) { + writer.appendNoHilight(" * ").appendNoHilight(decompilationErrorAdd).newLine(); + } + writer.appendNoHilight(" * ").appendNoHilight(AppResources.translate("decompilationError.errorType")). + appendNoHilight(": " + ex.getClass().getSimpleName() + " (" + ex.getMessage() + ")").newLine(); + writer.appendNoHilight(" */").newLine(); + writer.appendNoHilight("throw new flash.errors.IllegalOperationError(\""). + appendNoHilight(AppResources.translate("decompilationError.error.description")). + appendNoHilight("\");").newLine(); + } + + public static String escapeHTML(String text) { + String[] from = new String[]{"&", "<", ">", "\"", "'", "/"}; + String[] to = new String[]{"&", "<", ">", """, "'", "/"}; + for (int i = 0; i < from.length; i++) { + text = text.replace(from[i], to[i]); + } + return text; + } + + public static String removeInvalidXMLCharacters(String text) { + StringBuilder sb = new StringBuilder(text.length()); + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (ch > 31 || ch == 9 || ch == 10 || ch == 13) { + sb.append(ch); + } + } + + return sb.toString(); + } + + public static Shape imageToShapeOld(BufferedImage image) { + Area area = new Area(); + Rectangle rectangle = new Rectangle(); + int y1, y2; + int width = image.getWidth(); + int height = image.getHeight(); + + int[] imgData; + int type = image.getType(); + if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) { + imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + } else { + imgData = image.getRGB(0, 0, width, height, null, 0, width); + } + + BitSet bs = new BitSet(width * height); + bs.set(type); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + int idx = width * y + x; + if ((imgData[idx] >>> 24) > 0) { + bs.set(idx); + } + } + } + + String key = byteArrayToBase64String(bs.toByteArray()); + if (shapeCache.containsKey(key)) { + return shapeCache.get(key); + } + + for (int x = 0; x < width; x++) { + y1 = Integer.MAX_VALUE; + y2 = -1; + for (int y = 0; y < height; y++) { + int rgb = imgData[width * y + x]; + rgb = rgb >>> 24; + if (rgb > 0) { + if (y1 == Integer.MAX_VALUE) { + y1 = y; + y2 = y; + } + if (y > (y2 + 1)) { + rectangle.setBounds(x, y1, 1, y2 - y1 + 1); + area.add(new Area(rectangle)); + y1 = y; + } + y2 = y; + } + } + if ((y2 - y1) >= 0) { + rectangle.setBounds(x, y1, 1, y2 - y1 + 1); + area.add(new Area(rectangle)); + } + } + + shapeCache.put(key, area); + return area; + } + + public static Shape imageToShape(BufferedImage image) { + Area area = new Area(); + int width = image.getWidth(); + int height = image.getHeight(); + + int[] imgData; + int type = image.getType(); + if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) { + imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + } else { + imgData = image.getRGB(0, 0, width, height, null, 0, width); + } + + BitSet bs = new BitSet(width * height); + bs.set(type); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + int idx = width * y + x; + if ((imgData[idx] >>> 24) > 0) { + bs.set(idx); + } + } + } + + String key = byteArrayToBase64String(bs.toByteArray()); + if (shapeCache.containsKey(key)) { + return shapeCache.get(key); + } + + BitSet bsArea = new BitSet(width * height); + boolean modified = true; + + List leftCoordsX = new ArrayList<>(); + List leftCoordsY = new ArrayList<>(); + List rightCoordsX = new ArrayList<>(); + List rightCoordsY = new ArrayList<>(); + while (modified) { + modified = false; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int idx = width * y + x; + if ((imgData[idx] >>> 24) > 0 && !bsArea.get(idx)) { + leftCoordsX.clear(); + leftCoordsY.clear(); + rightCoordsX.clear(); + rightCoordsY.clear(); + int leftX = x; + int rightX = findRight(imgData, x, y, width); + leftCoordsX.add(leftX); + leftCoordsY.add(y); + rightCoordsX.add(rightX); + rightCoordsY.add(y); + setBitSet(bsArea, leftX, rightX, y, width); + int y2 = y + 1; + while (y2 < height) { + leftCoordsX.add(leftX); + leftCoordsY.add(y2); + rightCoordsX.add(rightX); + rightCoordsY.add(y2); + + int leftX2 = findFirst(imgData, leftX, rightX, y2, width); + if (leftX2 == -1) { + break; + } + + int rightX2 = findRight(imgData, leftX2, y2, width); + + if (leftX2 != leftX) { + leftCoordsX.add(leftX2); + leftCoordsY.add(y2); + } + + if (rightX2 != rightX) { + rightCoordsX.add(rightX2); + rightCoordsY.add(y2); + } + + leftX = leftX2; + rightX = rightX2; + + setBitSet(bsArea, leftX, rightX, y2, width); + y2++; + } + + int cnt = leftCoordsX.size() + rightCoordsX.size(); + int[] xCoords = new int[cnt]; + int[] yCoords = new int[cnt]; + for (int i = 0; i < rightCoordsX.size(); i++) { + xCoords[i] = rightCoordsX.get(i); + yCoords[i] = rightCoordsY.get(i); + } + + int offset = rightCoordsX.size(); + for (int i = 0; i < leftCoordsX.size(); i++) { + int idx2 = leftCoordsX.size() - i - 1; + xCoords[i + offset] = leftCoordsX.get(idx2); + yCoords[i + offset] = leftCoordsY.get(idx2); + } + + Area area2 = new Area(new Polygon(xCoords, yCoords, xCoords.length)); + area.add(area2); + modified = true; + } + } + } + } + + shapeCache.put(key, area); + return area; + } + + private static void setBitSet(BitSet bitSet, int x1, int x2, int y, int width) { + int idx = width * y + x1; + int idx2 = width * y + x2; + for (; idx < idx2; idx++) { + bitSet.set(idx); + } + } + + private static int findFirst(int[] imgData, int x1, int x2, int y, int width) { + int idx = width * y + x1; + if ((imgData[idx] >>> 24) > 0) { + while (x1 > 0 && (imgData[idx - 1] >>> 24) > 0) { + x1--; + idx--; + } + return x1; + } + + int idx2 = width * y + x2; + for (; idx < idx2; idx++) { + if ((imgData[idx] >>> 24) > 0) { + return x1; + } + + x1++; + } + + return -1; + } + + private static int findRight(int[] imgData, int x, int y, int width) { + int result = x; + int idx = width * y + x; + while (result < width && (imgData[idx] >>> 24) > 0) { + result++; + idx++; + } + + return result; + } + + public static void clearShapeCache() { + shapeCache.clear(); + } + + public static String byteArrayToBase64String(byte[] data) { + return DatatypeConverter.printBase64Binary(data); + } + + /** + * Formats double value (removes .0 from end) + * + * @param d + * @return String + */ + public static String doubleStr(double d) { + String ret = Double.toString(d); + if (ret.endsWith(".0")) { + ret = ret.substring(0, ret.length() - 2); + } + return ret; + } + + public static String byteCountStr(long bytes, boolean si) { + int unit = si ? 1000 : 1024; + if (bytes < unit) { + return bytes + " B"; + } + int exp = (int) (Math.log(bytes) / Math.log(unit)); + String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); + return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 385c7c438..520283e99 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -1,1541 +1,1541 @@ -/* - * Copyright (C) 2010-2015 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui; - -import com.jpexs.decompiler.flash.ApplicationInfo; -import com.jpexs.decompiler.flash.EventListener; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; -import com.jpexs.decompiler.flash.SWFSourceInfo; -import com.jpexs.decompiler.flash.SearchMode; -import com.jpexs.decompiler.flash.SwfOpenException; -import com.jpexs.decompiler.flash.Version; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; -import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; -import com.jpexs.decompiler.flash.console.ContextMenuTools; -import com.jpexs.decompiler.flash.exporters.modes.ExeExportMode; -import com.jpexs.decompiler.flash.gui.pipes.FirstInstance; -import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.treeitems.SWFList; -import com.jpexs.helpers.Cache; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.Path; -import com.jpexs.helpers.ProgressListener; -import com.jpexs.helpers.Stopwatch; -import com.jpexs.helpers.streams.SeekableInputStream; -import com.sun.jna.Platform; -import com.sun.jna.platform.win32.Advapi32Util; -import com.sun.jna.platform.win32.Kernel32; -import com.sun.jna.platform.win32.WinReg; -import java.awt.AWTException; -import java.awt.Frame; -import java.awt.GraphicsEnvironment; -import java.awt.MenuItem; -import java.awt.PopupMenu; -import java.awt.SystemTray; -import java.awt.TrayIcon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.URL; -import java.net.URLConnection; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.Map.Entry; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.logging.ConsoleHandler; -import java.util.logging.FileHandler; -import java.util.logging.Formatter; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.SwingWorker; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.filechooser.FileFilter; -import org.pushingpixels.substance.api.SubstanceLookAndFeel; - -/** - * Main executable class - * - * @author JPEXS - */ -public class Main { - - protected static ProxyFrame proxyFrame; - - private static List sourceInfos = new ArrayList<>(); - - public static LoadingDialog loadingDialog; - - private static boolean working = false; - - private static TrayIcon trayIcon; - - private static MenuItem stopMenuItem; - - private static MainFrame mainFrame; - - public static final int UPDATE_SYSTEM_MAJOR = 1; - - public static final int UPDATE_SYSTEM_MINOR = 3; - - private static LoadFromMemoryFrame loadFromMemoryFrame; - - private static LoadFromCacheFrame loadFromCacheFrame; - - private static final Logger logger = Logger.getLogger(Main.class.getName()); - - public static DebugLogDialog debugDialog; - - public static boolean shouldCloseWhenClosingLoadingDialog; - - public static void ensureMainFrame() { - if (mainFrame == null) { - synchronized (Main.class) { - if (mainFrame == null) { - MainFrame frame; - if (Configuration.useRibbonInterface.get()) { - frame = new MainFrameRibbon(); - } else { - frame = new MainFrameClassic(); - } - frame.getPanel().setErrorState(ErrorLogFrame.getInstance().getErrorState()); - mainFrame = frame; - } - } - } - } - - public static MainFrame getMainFrame() { - return mainFrame; - } - - public static void loadFromCache() { - if (loadFromCacheFrame == null) { - loadFromCacheFrame = new LoadFromCacheFrame(); - } - loadFromCacheFrame.setVisible(true); - } - - public static void loadFromMemory() { - if (loadFromMemoryFrame == null) { - loadFromMemoryFrame = new LoadFromMemoryFrame(mainFrame); - } - loadFromMemoryFrame.setVisible(true); - } - - public static void setSubLimiter(boolean value) { - if (value) { - AVM2Code.toSourceLimit = Configuration.sublimiter.get(); - } else { - AVM2Code.toSourceLimit = -1; - } - } - - public static boolean isWorking() { - return working; - } - - public static void startProxy(int port) { - if (proxyFrame == null) { - proxyFrame = new ProxyFrame(mainFrame); - } - - proxyFrame.setPort(port); - addTrayIcon(); - switchProxy(); - } - - public static void showProxy() { - if (proxyFrame == null) { - proxyFrame = new ProxyFrame(mainFrame); - } - proxyFrame.setVisible(true); - proxyFrame.setState(Frame.NORMAL); - } - - public static void startWork(String name) { - startWork(name, -1, null); - } - - public static void startWork(String name, int percent) { - startWork(name, percent, null); - } - - public static void startWork(String name, CancellableWorker worker) { - startWork(name, -1, worker); - } - - public static void startWork(final String name, final int percent, final CancellableWorker worker) { - working = true; - View.execInEventDispatchLater(() -> { - if (mainFrame != null) { - mainFrame.getPanel().setWorkStatus(name, worker); - if (percent == -1) { - mainFrame.getPanel().hidePercent(); - } else { - mainFrame.getPanel().setPercent(percent); - } - } - if (loadingDialog != null) { - loadingDialog.setDetail(name); - loadingDialog.setPercent(percent); - } - if (CommandLineArgumentParser.isCommandLineMode()) { - System.out.println(name); - } - }); - } - - public static void stopWork() { - working = false; - View.execInEventDispatchLater(() -> { - if (mainFrame != null) { - mainFrame.getPanel().setWorkStatus("", null); - } - if (loadingDialog != null) { - loadingDialog.setDetail(""); - } - }); - } - - public static SWFList parseSWF(SWFSourceInfo sourceInfo) throws Exception { - SWFList result = new SWFList(); - - InputStream inputStream = sourceInfo.getInputStream(); - SWFBundle bundle = null; - FileInputStream fis = null; - if (inputStream == null) { - inputStream = new BufferedInputStream(fis = new FileInputStream(sourceInfo.getFile())); - bundle = sourceInfo.getBundle(false, SearchMode.ALL); - logger.log(Level.INFO, "Load file: {0}", sourceInfo.getFile()); - } else if (inputStream instanceof SeekableInputStream - || inputStream instanceof BufferedInputStream) { - try { - inputStream.reset(); - } catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); - } - logger.log(Level.INFO, "Load stream: {0}", sourceInfo.getFileTitle()); - } - - Stopwatch sw = Stopwatch.startNew(); - if (bundle != null) { - result.bundle = bundle; - result.name = new File(sourceInfo.getFileTitleOrName()).getName(); - for (Entry streamEntry : bundle.getAll().entrySet()) { - InputStream stream = streamEntry.getValue(); - stream.reset(); - CancellableWorker worker = new CancellableWorker() { - @Override - public SWF doInBackground() throws Exception { - SWF swf = new SWF(stream, null, streamEntry.getKey(), new ProgressListener() { - @Override - public void progress(int p) { - startWork(AppStrings.translate("work.reading.swf"), p); - } - }, Configuration.parallelSpeedUp.get()); - return swf; - } - }; - loadingDialog.setWroker(worker); - worker.execute(); - - try { - result.add(worker.get()); - } catch (CancellationException ex) { - logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", streamEntry.getKey()); - } - } - } else { - InputStream fInputStream = inputStream; - CancellableWorker worker = new CancellableWorker() { - @Override - public SWF doInBackground() throws Exception { - SWF swf = new SWF(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle(), new ProgressListener() { - @Override - public void progress(int p) { - startWork(AppStrings.translate("work.reading.swf"), p); - } - }, Configuration.parallelSpeedUp.get()); - return swf; - } - }; - if (loadingDialog != null) { - loadingDialog.setWroker(worker); - } - worker.execute(); - - try { - result.add(worker.get()); - } catch (CancellationException ex) { - logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", sourceInfo.getFileTitleOrName()); - } - } - - if (fis != null) { - logger.log(Level.INFO, "File loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000)); - fis.close(); - } else { - logger.log(Level.INFO, "Stream loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000)); - } - - result.sourceInfo = sourceInfo; - for (SWF swf : result) { - logger.log(Level.INFO, ""); - logger.log(Level.INFO, "== File information =="); - logger.log(Level.INFO, "Size: {0}", Helper.formatFileSize(swf.fileSize)); - logger.log(Level.INFO, "Flash version: {0}", swf.version); - int width = (int) ((swf.displayRect.Xmax - swf.displayRect.Xmin) / SWF.unitDivisor); - int height = (int) ((swf.displayRect.Ymax - swf.displayRect.Ymin) / SWF.unitDivisor); - logger.log(Level.INFO, "Width: {0}", width); - logger.log(Level.INFO, "Height: {0}", height); - - swf.swfList = result; - swf.addEventListener(new EventListener() { - @Override - public void handleExportingEvent(String type, int index, int count, Object data) { - String text = AppStrings.translate("work.exporting"); - if (type != null && type.length() > 0) { - text += " " + type; - } - - startWork(text + " " + index + "/" + count + " " + data); - } - - @Override - public void handleExportedEvent(String type, int index, int count, Object data) { - String text = AppStrings.translate("work.exported"); - if (type != null && type.length() > 0) { - text += " " + type; - } - - startWork(text + " " + index + "/" + count + " " + data); - } - - @Override - public void handleEvent(String event, Object data) { - if (event.equals("exporting") || event.equals("exported")) { - throw new Error("Event is not supported by this handler."); - } - if (event.equals("getVariables")) { - startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); - } - if (event.equals("deobfuscate")) { - startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); - } - if (event.equals("rename")) { - startWork(AppStrings.translate("work.renaming") + "..." + (String) data); - } - } - }); - } - - return result; - } - - public static void saveFile(SWF swf, String outfile) throws IOException { - saveFile(swf, outfile, SaveFileMode.SAVE, null); - } - - public static void saveFile(SWF swf, String outfile, SaveFileMode mode, ExeExportMode exeExportMode) throws IOException { - if (mode == SaveFileMode.SAVEAS && !swf.swfList.isBundle()) { - swf.setFile(outfile); - swf.swfList.sourceInfo.setFile(outfile); - } - File outfileF = new File(outfile); - File tmpFile = new File(outfile + ".tmp"); - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(tmpFile))) { - if (mode == SaveFileMode.EXE) { - switch (exeExportMode) { - case WRAPPER: - InputStream exeStream = View.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/Swf2Exe.bin"); - byte[] buffer = new byte[4096]; - int bytesRead; - while ((bytesRead = exeStream.read(buffer)) != -1) { - fos.write(buffer, 0, bytesRead); - } - int width = swf.displayRect.Xmax - swf.displayRect.Xmin; - int height = swf.displayRect.Ymax - swf.displayRect.Ymin; - fos.write(width & 0xff); - fos.write((width >> 8) & 0xff); - fos.write((width >> 16) & 0xff); - fos.write((width >> 24) & 0xff); - fos.write(height & 0xff); - fos.write((height >> 8) & 0xff); - fos.write((height >> 16) & 0xff); - fos.write((height >> 24) & 0xff); - fos.write(Configuration.saveAsExeScaleMode.get()); - break; - case PROJECTOR_WIN: - // todo - break; - case PROJECTOR_MAC: - // todo - break; - } - } - swf.saveTo(fos); - } - if (tmpFile.exists()) { - if (tmpFile.length() > 0) { - outfileF.delete(); - if (!tmpFile.renameTo(outfileF)) { - tmpFile.delete(); - throw new IOException("Cannot access " + outfile); - } - } else { - throw new IOException("Output is empty"); - } - } - } - - private static class OpenFileWorker extends SwingWorker { - - private final SWFSourceInfo[] sourceInfos; - - private final Runnable executeAfterOpen; - - public OpenFileWorker(SWFSourceInfo sourceInfo) { - this(sourceInfo, null); - } - - public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { - this.sourceInfos = new SWFSourceInfo[]{sourceInfo}; - this.executeAfterOpen = executeAfterOpen; - } - - public OpenFileWorker(SWFSourceInfo[] sourceInfos) { - this(sourceInfos, null); - } - - public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen) { - this.sourceInfos = sourceInfos; - this.executeAfterOpen = executeAfterOpen; - } - - @Override - protected Object doInBackground() throws Exception { - boolean first = true; - SWF firstSWF = null; - for (final SWFSourceInfo sourceInfo : sourceInfos) { - SWFList swfs = null; - try { - Main.startWork(AppStrings.translate("work.reading.swf") + "..."); - try { - swfs = parseSWF(sourceInfo); - } catch (ExecutionException ex) { - Throwable cause = ex.getCause(); - if (cause instanceof SwfOpenException) { - throw (SwfOpenException) cause; - } - - throw ex; - } - } catch (OutOfMemoryError ex) { - logger.log(Level.SEVERE, null, ex); - View.showMessageDialog(null, "Cannot load SWF file. Out of memory."); - continue; - } catch (SwfOpenException ex) { - logger.log(Level.SEVERE, null, ex); - View.showMessageDialog(null, ex.getMessage()); - continue; - } catch (Exception ex) { - logger.log(Level.SEVERE, null, ex); - View.showMessageDialog(null, "Cannot load SWF file."); - continue; - } - - final SWFList swfs1 = swfs; - final boolean first1 = first; - first = false; - if (firstSWF == null) { - firstSWF = swfs1.get(0); - } - - try { - View.execInEventDispatch(() -> { - Main.startWork(AppStrings.translate("work.creatingwindow") + "..."); - ensureMainFrame(); - mainFrame.getPanel().load(swfs1, first1); - }); - } catch (Exception ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - loadingDialog.setVisible(false); - shouldCloseWhenClosingLoadingDialog = false; - - final SWF fswf = firstSWF; - View.execInEventDispatch(() -> { - if (mainFrame != null) { - mainFrame.setVisible(true); - } - - Main.stopWork(); - - if (mainFrame != null && Configuration.gotoMainClassOnStartup.get()) { - mainFrame.getPanel().gotoDocumentClass(fswf); - } - - if (mainFrame != null && fswf != null) { - SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(fswf.getShortFileName()); - if (swfConf != null) { - String pathStr = swfConf.lastSelectedPath; - mainFrame.getPanel().tagTree.setSelectionPathString(pathStr); - } - } - - if (executeAfterOpen != null) { - executeAfterOpen.run(); - } - }); - - return true; - } - } - - public static boolean reloadSWFs() { - CancellableWorker.cancelBackgroundThreads(); - if (Main.sourceInfos.isEmpty()) { - Helper.freeMem(); - showModeFrame(); - return true; - } else { - SWFSourceInfo[] sourceInfosCopy = new SWFSourceInfo[sourceInfos.size()]; - sourceInfos.toArray(sourceInfosCopy); - sourceInfos.clear(); - openFile(sourceInfosCopy); - return true; - } - } - - public static void reloadApp() { - if (debugDialog != null) { - debugDialog.setVisible(false); - debugDialog.dispose(); - debugDialog = null; - } - if (loadingDialog != null) { - synchronized (Main.class) { - if (loadingDialog != null) { - loadingDialog.setVisible(false); - loadingDialog.dispose(); - loadingDialog = null; - } - } - } - if (proxyFrame != null) { - proxyFrame.setVisible(false); - proxyFrame.dispose(); - proxyFrame = null; - } - if (loadFromMemoryFrame != null) { - loadFromMemoryFrame.setVisible(false); - loadFromMemoryFrame.dispose(); - loadFromMemoryFrame = null; - } - if (loadFromCacheFrame != null) { - loadFromCacheFrame.setVisible(false); - loadFromCacheFrame.dispose(); - loadFromCacheFrame = null; - } - if (mainFrame != null) { - mainFrame.setVisible(false); - mainFrame.getPanel().closeAll(); - mainFrame.dispose(); - mainFrame = null; - } - FontTag.reload(); - Cache.clearAll(); - initGui(); - reloadSWFs(); - } - - public static OpenFileResult openFile(String swfFile, String fileTitle) { - return openFile(swfFile, fileTitle, null); - } - - public static OpenFileResult openFile(String swfFile, String fileTitle, Runnable executeAfterOpen) { - try { - File file = new File(swfFile); - if (!file.exists()) { - View.showMessageDialog(null, AppStrings.translate("open.error.fileNotFound"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); - return OpenFileResult.NOT_FOUND; - } - swfFile = file.getCanonicalPath(); - Configuration.addRecentFile(swfFile); - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, swfFile, fileTitle); - OpenFileResult openResult = openFile(sourceInfo); - return openResult; - } catch (IOException ex) { - View.showMessageDialog(null, AppStrings.translate("open.error.cannotOpen"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); - return OpenFileResult.ERROR; - } - } - - public static OpenFileResult openFile(SWFSourceInfo sourceInfo) { - return openFile(new SWFSourceInfo[]{sourceInfo}); - } - - public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { - return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen); - } - - public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos) { - return openFile(newSourceInfos, null); - } - - public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen) { - if (mainFrame != null && !Configuration.openMultipleFiles.get()) { - sourceInfos.clear(); - mainFrame.getPanel().closeAll(); - mainFrame.setVisible(false); - Helper.freeMem(); - } - - loadingDialog.setVisible(true); - OpenFileWorker wrk = new OpenFileWorker(newSourceInfos, executeAfterOpen); - wrk.execute(); - sourceInfos.addAll(Arrays.asList(newSourceInfos)); - return OpenFileResult.OK; - } - - public static void closeFile(SWFList swf) { - sourceInfos.remove(swf.sourceInfo); - mainFrame.getPanel().close(swf); - } - - public static void closeAll() { - sourceInfos.clear(); - mainFrame.getPanel().closeAll(); - } - - public static boolean saveFileDialog(SWF swf, final SaveFileMode mode) { - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get())); - String ext = ".swf"; - switch (mode) { - case SAVE: - case SAVEAS: - if (swf.getFile() != null) { - ext = Path.getExtension(swf.getFile()); - } - break; - case EXE: - ext = ".exe"; - break; - } - - FileFilter swfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.swf"); - } - }; - - FileFilter gfxFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.gfx"); - } - }; - - ExeExportMode exeExportMode = null; - if (mode == SaveFileMode.EXE) { - exeExportMode = Configuration.exeExportMode.get(); - String filterDescription = null; - switch (exeExportMode) { - case WRAPPER: - ext = ".exe"; - filterDescription = "filter.exe"; - break; - case PROJECTOR_WIN: - ext = ".exe"; - filterDescription = "filter.exe"; - break; - case PROJECTOR_MAC: - ext = ".dmg"; - filterDescription = "filter.dmg"; - break; - /*case PROJECTOR_LINUX: - // linux projector is compressed with tar.gz - // todo: decompress - ext = ""; - filterDescription = "filter.linuxExe"; - break;*/ - } - - String fext = ext; - String ffilterDescription = filterDescription; - FileFilter exeFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(fext)) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate(ffilterDescription); - } - }; - fc.setFileFilter(exeFilter); - } else { - if (swf.gfx) { - fc.addChoosableFileFilter(swfFilter); - fc.setFileFilter(gfxFilter); - } else { - fc.setFileFilter(swfFilter); - fc.addChoosableFileFilter(gfxFilter); - } - } - final String extension = ext; - fc.setAcceptAllFileFilterUsed(false); - JFrame f = new JFrame(); - View.setWindowIcon(f); - if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) { - File file = Helper.fixDialogFile(fc.getSelectedFile()); - FileFilter selFilter = fc.getFileFilter(); - try { - String fileName = file.getAbsolutePath(); - if (selFilter == swfFilter) { - if (!fileName.toLowerCase().endsWith(extension)) { - fileName += extension; - } - swf.gfx = false; - } - if (selFilter == gfxFilter) { - if (!fileName.toLowerCase().endsWith(".gfx")) { - fileName += ".gfx"; - } - swf.gfx = true; - } - Main.saveFile(swf, fileName, mode, exeExportMode); - Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath()); - return true; - } catch (IOException ex) { - View.showMessageDialog(null, AppStrings.translate("error.file.write")); - } - } - return false; - } - - public static boolean openFileDialog() { - JFileChooser fc = new JFileChooser(); - if (Configuration.openMultipleFiles.get()) { - fc.setMultiSelectionEnabled(true); - } - fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); - FileFilter allSupportedFilter = new FileFilter() { - private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip"}; - - @Override - public boolean accept(File f) { - String name = f.getName().toLowerCase(); - for (String ext : supportedExtensions) { - if (name.endsWith(ext)) { - return true; - } - } - return f.isDirectory(); - } - - @Override - public String getDescription() { - String exts = Helper.joinStrings(supportedExtensions, "*%s", "; "); - return AppStrings.translate("filter.supported") + " (" + exts + ")"; - } - }; - fc.setFileFilter(allSupportedFilter); - FileFilter swfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.swf"); - } - }; - fc.addChoosableFileFilter(swfFilter); - - FileFilter swcFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".swc")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.swc"); - } - }; - fc.addChoosableFileFilter(swcFilter); - - FileFilter gfxFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.gfx"); - } - }; - fc.addChoosableFileFilter(gfxFilter); - - FileFilter zipFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".zip")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.zip"); - } - }; - fc.addChoosableFileFilter(zipFilter); - - FileFilter binaryFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return true; - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.binary"); - } - }; - fc.addChoosableFileFilter(binaryFilter); - - fc.setAcceptAllFileFilterUsed(false); - JFrame f = new JFrame(); - View.setWindowIcon(f); - int returnVal = fc.showOpenDialog(f); - if (returnVal == JFileChooser.APPROVE_OPTION) { - Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); - File[] selFiles = fc.getSelectedFiles(); - for (File file : selFiles) { - File selfile = Helper.fixDialogFile(file); - Main.openFile(selfile.getAbsolutePath(), null); - } - return true; - } else { - return false; - } - } - - public static void displayErrorFrame() { - ErrorLogFrame.getInstance().setVisible(true); - } - - private static void initGui() { - if (GraphicsEnvironment.isHeadless()) { - System.err.println("Error: Your system does not support Graphic User Interface"); - exit(); - } - if (Configuration.useRibbonInterface.get()) { - View.setLookAndFeel(); - } else { - try { - UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, null); - UIManager.put("Tree.expandedIcon", null); - UIManager.put("Tree.collapsedIcon", null); - UIManager.put("ColorChooserUI", null); - UIManager.put("ColorChooser.swatchesRecentSwatchSize", null); - UIManager.put("ColorChooser.swatchesSwatchSize", null); - UIManager.put("RibbonApplicationMenuPopupPanelUI", null); - UIManager.put("RibbonApplicationMenuButtonUI", null); - UIManager.put("ProgressBarUI", null); - UIManager.put("TextField.background", null); - UIManager.put("FormattedTextField.background", null); - UIManager.put("CommandButtonUI", null); - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - ErrorLogFrame.createNewInstance(); - - autoCheckForUpdates(); - offerAssociation(); - loadingDialog = new LoadingDialog(); - } - - public static void showModeFrame() { - ensureMainFrame(); - mainFrame.setVisible(true); - } - - private static void offerAssociation() { - boolean offered = Configuration.offeredAssociation.get(); - if (!offered) { - if (Platform.isWindows()) { - if ((!ContextMenuTools.isAddedToContextMenu()) && View.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { - ContextMenuTools.addToContextMenu(true, false); - } - } - - Configuration.offeredAssociation.set(true); - } - } - - public static void initLang() { - if (GraphicsEnvironment.isHeadless()) { //No GUI in OS - return; - } - if (!Configuration.locale.hasValue()) { - if (Platform.isWindows()) { - //Load from Installer - String uninstKey = "{E618D276-6596-41F4-8A98-447D442A77DB}_is1"; - uninstKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uninstKey; - try { - if (Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey)) { - if (Advapi32Util.registryValueExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language")) { - String installedLoc = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language"); - int lcid = Integer.parseInt(installedLoc); - char buf[] = new char[9]; - int cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO639LANGNAME, buf, 9); - String langCode = new String(buf, 0, cnt).trim().toLowerCase(); - - cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO3166CTRYNAME, buf, 9); - String countryCode = new String(buf, 0, cnt).trim().toLowerCase(); - - List langs = Arrays.asList(SelectLanguageDialog.getAvailableLanguages()); - for (int i = 0; i < langs.size(); i++) { - langs.set(i, langs.get(i).toLowerCase()); - } - - String selectedLang = null; - - if (langs.contains(langCode + "-" + countryCode)) { - selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode + "-" + countryCode)]; - } else if (langs.contains(langCode)) { - selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode)]; - } - if (selectedLang != null) { - Configuration.locale.set(selectedLang); - } - } - } - } catch (Exception ex) { - //ignore - } - } - } - Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get())); - AppStrings.updateLanguage(); - - try { - Class cl = Class.forName("org.pushingpixels.substance.api.SubstanceLookAndFeel"); - Field field = cl.getDeclaredField("LABEL_BUNDLE"); - field.setAccessible(true); - field.set(null, null); - } catch (Throwable ex) { - logger.log(Level.SEVERE, null, ex); - } - - UIManager.put("OptionPane.okButtonText", AppStrings.translate("button.ok")); - UIManager.put("OptionPane.yesButtonText", AppStrings.translate("button.yes")); - UIManager.put("OptionPane.noButtonText", AppStrings.translate("button.no")); - UIManager.put("OptionPane.cancelButtonText", AppStrings.translate("button.cancel")); - UIManager.put("OptionPane.messageDialogTitle", AppStrings.translate("dialog.message.title")); - UIManager.put("OptionPane.titleText", AppStrings.translate("dialog.select.title")); - - UIManager.put("FileChooser.acceptAllFileFilterText", AppStrings.translate("FileChooser.acceptAllFileFilterText")); - UIManager.put("FileChooser.lookInLabelText", AppStrings.translate("FileChooser.lookInLabelText")); - UIManager.put("FileChooser.cancelButtonText", AppStrings.translate("button.cancel")); - UIManager.put("FileChooser.cancelButtonToolTipText", AppStrings.translate("button.cancel")); - UIManager.put("FileChooser.openButtonText", AppStrings.translate("FileChooser.openButtonText")); - UIManager.put("FileChooser.openButtonToolTipText", AppStrings.translate("FileChooser.openButtonToolTipText")); - UIManager.put("FileChooser.filesOfTypeLabelText", AppStrings.translate("FileChooser.filesOfTypeLabelText")); - UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); - UIManager.put("FileChooser.listViewButtonToolTipText", AppStrings.translate("FileChooser.listViewButtonToolTipText")); - UIManager.put("FileChooser.listViewButtonAccessibleName", AppStrings.translate("FileChooser.listViewButtonAccessibleName")); - UIManager.put("FileChooser.detailsViewButtonToolTipText", AppStrings.translate("FileChooser.detailsViewButtonToolTipText")); - UIManager.put("FileChooser.detailsViewButtonAccessibleName", AppStrings.translate("FileChooser.detailsViewButtonAccessibleName")); - UIManager.put("FileChooser.upFolderToolTipText", AppStrings.translate("FileChooser.upFolderToolTipText")); - UIManager.put("FileChooser.upFolderAccessibleName", AppStrings.translate("FileChooser.upFolderAccessibleName")); - UIManager.put("FileChooser.homeFolderToolTipText", AppStrings.translate("FileChooser.homeFolderToolTipText")); - UIManager.put("FileChooser.homeFolderAccessibleName", AppStrings.translate("FileChooser.homeFolderAccessibleName")); - UIManager.put("FileChooser.fileNameHeaderText", AppStrings.translate("FileChooser.fileNameHeaderText")); - UIManager.put("FileChooser.fileSizeHeaderText", AppStrings.translate("FileChooser.fileSizeHeaderText")); - UIManager.put("FileChooser.fileTypeHeaderText", AppStrings.translate("FileChooser.fileTypeHeaderText")); - UIManager.put("FileChooser.fileDateHeaderText", AppStrings.translate("FileChooser.fileDateHeaderText")); - UIManager.put("FileChooser.fileAttrHeaderText", AppStrings.translate("FileChooser.fileAttrHeaderText")); - UIManager.put("FileChooser.openDialogTitleText", AppStrings.translate("FileChooser.openDialogTitleText")); - UIManager.put("FileChooser.directoryDescriptionText", AppStrings.translate("FileChooser.directoryDescriptionText")); - UIManager.put("FileChooser.directoryOpenButtonText", AppStrings.translate("FileChooser.directoryOpenButtonText")); - UIManager.put("FileChooser.directoryOpenButtonToolTipText", AppStrings.translate("FileChooser.directoryOpenButtonToolTipText")); - UIManager.put("FileChooser.fileDescriptionText", AppStrings.translate("FileChooser.fileDescriptionText")); - UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); - UIManager.put("FileChooser.helpButtonText", AppStrings.translate("FileChooser.helpButtonText")); - UIManager.put("FileChooser.helpButtonToolTipText", AppStrings.translate("FileChooser.helpButtonToolTipText")); - UIManager.put("FileChooser.newFolderAccessibleName", AppStrings.translate("FileChooser.newFolderAccessibleName")); - UIManager.put("FileChooser.newFolderErrorText", AppStrings.translate("FileChooser.newFolderErrorText")); - UIManager.put("FileChooser.newFolderToolTipText", AppStrings.translate("FileChooser.newFolderToolTipText")); - UIManager.put("FileChooser.other.newFolder", AppStrings.translate("FileChooser.other.newFolder")); - UIManager.put("FileChooser.other.newFolder.subsequent", AppStrings.translate("FileChooser.other.newFolder.subsequent")); - UIManager.put("FileChooser.win32.newFolder", AppStrings.translate("FileChooser.win32.newFolder")); - UIManager.put("FileChooser.win32.newFolder.subsequent", AppStrings.translate("FileChooser.win32.newFolder.subsequent")); - UIManager.put("FileChooser.saveButtonText", AppStrings.translate("FileChooser.saveButtonText")); - UIManager.put("FileChooser.saveButtonToolTipText", AppStrings.translate("FileChooser.saveButtonToolTipText")); - UIManager.put("FileChooser.saveDialogTitleText", AppStrings.translate("FileChooser.saveDialogTitleText")); - UIManager.put("FileChooser.saveInLabelText", AppStrings.translate("FileChooser.saveInLabelText")); - UIManager.put("FileChooser.updateButtonText", AppStrings.translate("FileChooser.updateButtonText")); - UIManager.put("FileChooser.updateButtonToolTipText", AppStrings.translate("FileChooser.updateButtonToolTipText")); - - UIManager.put("FileChooser.detailsViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewActionLabel.textAndMnemonic")); - UIManager.put("FileChooser.detailsViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewButtonToolTip.textAndMnemonic")); - UIManager.put("FileChooser.fileAttrHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileAttrHeader.textAndMnemonic")); - UIManager.put("FileChooser.fileDateHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileDateHeader.textAndMnemonic")); - UIManager.put("FileChooser.fileNameHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileNameHeader.textAndMnemonic")); - UIManager.put("FileChooser.fileNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.fileNameLabel.textAndMnemonic")); - UIManager.put("FileChooser.fileSizeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileSizeHeader.textAndMnemonic")); - UIManager.put("FileChooser.fileTypeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileTypeHeader.textAndMnemonic")); - UIManager.put("FileChooser.filesOfTypeLabel.textAndMnemonic", AppStrings.translate("FileChooser.filesOfTypeLabel.textAndMnemonic")); - UIManager.put("FileChooser.folderNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.folderNameLabel.textAndMnemonic")); - UIManager.put("FileChooser.homeFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.homeFolderToolTip.textAndMnemonic")); - UIManager.put("FileChooser.listViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.listViewActionLabel.textAndMnemonic")); - UIManager.put("FileChooser.listViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.listViewButtonToolTip.textAndMnemonic")); - UIManager.put("FileChooser.lookInLabel.textAndMnemonic", AppStrings.translate("FileChooser.lookInLabel.textAndMnemonic")); - UIManager.put("FileChooser.newFolderActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.newFolderActionLabel.textAndMnemonic")); - UIManager.put("FileChooser.newFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.newFolderToolTip.textAndMnemonic")); - UIManager.put("FileChooser.refreshActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.refreshActionLabel.textAndMnemonic")); - UIManager.put("FileChooser.saveInLabel.textAndMnemonic", AppStrings.translate("FileChooser.saveInLabel.textAndMnemonic")); - UIManager.put("FileChooser.upFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.upFolderToolTip.textAndMnemonic")); - UIManager.put("FileChooser.viewMenuButtonAccessibleName", AppStrings.translate("FileChooser.viewMenuButtonAccessibleName")); - UIManager.put("FileChooser.viewMenuButtonToolTipText", AppStrings.translate("FileChooser.viewMenuButtonToolTipText")); - UIManager.put("FileChooser.viewMenuLabel.textAndMnemonic", AppStrings.translate("FileChooser.viewMenuLabel.textAndMnemonic")); - UIManager.put("FileChooser.newFolderActionLabelText", AppStrings.translate("FileChooser.newFolderActionLabelText")); - UIManager.put("FileChooser.listViewActionLabelText", AppStrings.translate("FileChooser.listViewActionLabelText")); - UIManager.put("FileChooser.detailsViewActionLabelText", AppStrings.translate("FileChooser.detailsViewActionLabelText")); - UIManager.put("FileChooser.refreshActionLabelText", AppStrings.translate("FileChooser.refreshActionLabelText")); - UIManager.put("FileChooser.sortMenuLabelText", AppStrings.translate("FileChooser.sortMenuLabelText")); - UIManager.put("FileChooser.viewMenuLabelText", AppStrings.translate("FileChooser.viewMenuLabelText")); - UIManager.put("FileChooser.fileSizeKiloBytes", AppStrings.translate("FileChooser.fileSizeKiloBytes")); - UIManager.put("FileChooser.fileSizeMegaBytes", AppStrings.translate("FileChooser.fileSizeMegaBytes")); - UIManager.put("FileChooser.fileSizeGigaBytes", AppStrings.translate("FileChooser.fileSizeGigaBytes")); - UIManager.put("FileChooser.folderNameLabelText", AppStrings.translate("FileChooser.folderNameLabelText")); - - UIManager.put("ColorChooser.okText", AppStrings.translate("ColorChooser.okText")); - UIManager.put("ColorChooser.cancelText", AppStrings.translate("ColorChooser.cancelText")); - UIManager.put("ColorChooser.resetText", AppStrings.translate("ColorChooser.resetText")); - UIManager.put("ColorChooser.previewText", AppStrings.translate("ColorChooser.previewText")); - UIManager.put("ColorChooser.swatchesNameText", AppStrings.translate("ColorChooser.swatchesNameText")); - UIManager.put("ColorChooser.swatchesRecentText", AppStrings.translate("ColorChooser.swatchesRecentText")); - UIManager.put("ColorChooser.sampleText", AppStrings.translate("ColorChooser.sampleText")); - - Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable"); - } - - /** - * Clear old FFDec/JavactiveX temp files - */ - private static void clearTemp() { - String tempDirPath = System.getProperty("java.io.tmpdir"); - if (tempDirPath == null) { - return; - } - File tempDir = new File(tempDirPath); - if (!tempDir.exists()) { - return; - } - File delFiles[] = tempDir.listFiles(new FilenameFilter() { - - @Override - public boolean accept(File dir, String name) { - return name.matches("ffdec_cache.*\\.tmp") || name.matches("javactivex_.*\\.exe") || name.matches("temp[0-9]+\\.swf") || name.matches("ffdec_view_.*\\.swf"); - } - }); - for (File f : delFiles) { - try { - f.delete(); - } catch (Exception ex) { - //ignore - } - } - } - - /** - * @param args the command line arguments - * @throws IOException On error - */ - public static void main(String[] args) throws IOException { - - clearTemp(); - String pluginPath = Configuration.pluginPath.get(); - if (pluginPath != null && !pluginPath.isEmpty()) { - try { - SWFDecompilerPlugin.loadPlugin(pluginPath); - } catch (Throwable e) { - View.showMessageDialog(null, "Failed to load plugin: " + pluginPath); - } - } - - AppStrings.setResourceClass(MainFrame.class); - initLogging(Configuration.debugMode.get()); - initLang(); - - if (Configuration.cacheOnDisk.get()) { - Cache.setStorageType(Cache.STORAGE_FILES); - } else { - Cache.setStorageType(Cache.STORAGE_MEMORY); - } - - if (args.length == 0) { - View.execInEventDispatch(() -> { - initGui(); - if (Configuration.allowOnlyOneInstance.get() && FirstInstance.focus()) { //Try to focus first instance - Main.exit(); - } else { - showModeFrame(); - reloadLastSession(); - } - }); - } else { - String[] filesToOpen = CommandLineArgumentParser.parseArguments(args); - if (filesToOpen != null && filesToOpen.length > 0) { - View.execInEventDispatch(() -> { - initGui(); - shouldCloseWhenClosingLoadingDialog = true; - if (Configuration.allowOnlyOneInstance.get() && FirstInstance.openFiles(Arrays.asList(filesToOpen))) { //Try to open in first instance - Main.exit(); - } else { - for (String fileToOpen : filesToOpen) { - openFile(fileToOpen, null); - } - } - }); - } - } - } - - private static void reloadLastSession() { - if (Configuration.saveSessionOnExit.get()) { - String lastSession = Configuration.lastSessionFiles.get(); - if (lastSession != null && lastSession.length() > 0) { - String[] filesToOpen = lastSession.split(File.pathSeparator, -1); - List exfiles = new ArrayList<>(); - for (int i = 0; i < filesToOpen.length; i++) { - if (new File(filesToOpen[i]).exists()) { - exfiles.add(filesToOpen[i]); - } - } - SWFSourceInfo[] sourceInfos = new SWFSourceInfo[exfiles.size()]; - for (int i = 0; i < exfiles.size(); i++) { - sourceInfos[i] = new SWFSourceInfo(null, exfiles.get(i), null); - } - if (sourceInfos.length > 0) { - openFile(sourceInfos, () -> { - mainFrame.getPanel().tagTree.setSelectionPathString(Configuration.lastSessionSelection.get()); - }); - } - } - } - } - - public static String tempFile(String url) throws IOException { - File f = new File(Configuration.getFFDecHome() + "saved" + File.separator); - Path.createDirectorySafe(f); - return Configuration.getFFDecHome() + "saved" + File.separator + "asdec_" + Integer.toHexString(url.hashCode()) + ".tmp"; - } - - public static void removeTrayIcon() { - if (SystemTray.isSupported()) { - SystemTray tray = SystemTray.getSystemTray(); - if (trayIcon != null) { - tray.remove(trayIcon); - trayIcon = null; - } - } - } - - public static void switchProxy() { - proxyFrame.switchState(); - if (stopMenuItem != null) { - if (proxyFrame.isRunning()) { - stopMenuItem.setLabel(AppStrings.translate("proxy.stop")); - } else { - stopMenuItem.setLabel(AppStrings.translate("proxy.start")); - } - } - } - - public static void addTrayIcon() { - if (trayIcon != null) { - return; - } - if (SystemTray.isSupported()) { - SystemTray tray = SystemTray.getSystemTray(); - trayIcon = new TrayIcon(View.loadImage("proxy16"), ApplicationInfo.VENDOR + " " + ApplicationInfo.SHORT_APPLICATION_NAME + " " + AppStrings.translate("proxy")); - trayIcon.setImageAutoSize(true); - PopupMenu trayPopup = new PopupMenu(); - - ActionListener trayListener = new ActionListener() { - /** - * Invoked when an action occurs. - */ - @Override - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("EXIT")) { - Main.exit(); - } - if (e.getActionCommand().equals("SHOW")) { - Main.showProxy(); - } - if (e.getActionCommand().equals("SWITCH")) { - Main.switchProxy(); - } - } - }; - - MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show")); - showMenuItem.setActionCommand("SHOW"); - showMenuItem.addActionListener(trayListener); - trayPopup.add(showMenuItem); - stopMenuItem = new MenuItem(AppStrings.translate("proxy.start")); - stopMenuItem.setActionCommand("SWITCH"); - stopMenuItem.addActionListener(trayListener); - trayPopup.add(stopMenuItem); - trayPopup.addSeparator(); - MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit")); - exitMenuItem.setActionCommand("EXIT"); - exitMenuItem.addActionListener(trayListener); - trayPopup.add(exitMenuItem); - - trayIcon.setPopupMenu(trayPopup); - trayIcon.addMouseListener(new MouseAdapter() { - /** - * {@inheritDoc} - */ - @Override - public void mouseClicked(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON1) { - Main.showProxy(); - } - } - }); - try { - tray.add(trayIcon); - } catch (AWTException ex) { - } - } - } - - public static void exit() { - Configuration.saveConfig(); - if (mainFrame != null && mainFrame.getPanel() != null) { - mainFrame.getPanel().unloadFlashPlayer(); - } - System.exit(0); - } - - public static void about() { - (new AboutDialog()).setVisible(true); - } - - public static void advancedSettings() { - (new AdvancedSettingsDialog()).setVisible(true); - } - - public static void autoCheckForUpdates() { - if (Configuration.checkForUpdatesAuto.get()) { - Calendar lastUpdatesCheckDate = Configuration.lastUpdatesCheckDate.get(); - if ((lastUpdatesCheckDate == null) || (lastUpdatesCheckDate.getTime().getTime() < Calendar.getInstance().getTime().getTime() - Configuration.checkForUpdatesDelay.get())) { - new SwingWorker() { - @Override - protected Object doInBackground() throws Exception { - checkForUpdates(); - return null; - } - }.execute(); - } - } - } - - public static boolean checkForUpdates() { - String currentVersion = ApplicationInfo.version; - if (currentVersion.equals("unknown")) { - // sometimes during development the version information is not available - return false; - } - - List accepted = new ArrayList<>(); - if (Configuration.checkForUpdatesStable.get()) { - accepted.add("stable"); - } - if (Configuration.checkForUpdatesNightly.get()) { - accepted.add("nightly"); - } - - if (accepted.isEmpty()) { - return false; - } - - String acceptVersions = String.join(",", accepted); - try { - String proxyAddress = Configuration.updateProxyAddress.get(); - URL url = new URL(ApplicationInfo.updateCheckUrl); - - URLConnection uc = null; - if (proxyAddress != null && !proxyAddress.isEmpty()) { - int port = 8080; - if (proxyAddress.contains(":")) { - String[] parts = proxyAddress.split(":"); - port = Integer.parseInt(parts[1]); - proxyAddress = parts[0]; - } - - uc = url.openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, port))); - } else { - uc = url.openConnection(); - } - uc.setRequestProperty("X-Accept-Versions", acceptVersions); - uc.setRequestProperty("X-Update-Major", "" + UPDATE_SYSTEM_MAJOR); - uc.setRequestProperty("X-Update-Minor", "" + UPDATE_SYSTEM_MINOR); - uc.setRequestProperty("User-Agent", ApplicationInfo.shortApplicationVerName); - String currentLoc = Configuration.locale.get("en"); - uc.setRequestProperty("Accept-Language", currentLoc + ("en".equals(currentLoc) ? "" : ", en;q=0.8")); - - uc.connect(); - - BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream())); - String s; - final java.util.List versions = new ArrayList<>(); - String header = ""; - Pattern headerPat = Pattern.compile("\\[([a-zA-Z0-9]+)\\]"); - int updateMajor; - int updateMinor; - Version ver = null; - while ((s = br.readLine()) != null) { - - Matcher m = headerPat.matcher(s); - if (m.matches()) { - header = m.group(1); - if (header.equals("version")) { - ver = new Version(); - versions.add(ver); - } - if (header.equals("noversion")) { - break; - } - } else { - if (s.contains("=")) { - String key = s.substring(0, s.indexOf('=')); - String val = s.substring(s.indexOf('=') + 1); - if ("updateSystem".equals(header)) { - if (key.equals("majorVersion")) { - updateMajor = Integer.parseInt(val); - if (updateMajor > UPDATE_SYSTEM_MAJOR) { - break; - } - } - if (key.equals("minorVersion")) { - updateMinor = Integer.parseInt(val); - } - } - if ("version".equals(header) && (ver != null)) { - if (key.equals("versionId")) { - ver.versionId = Integer.parseInt(val); - } - if (key.equals("versionName")) { - ver.versionName = val; - } - if (key.equals("nightly")) { - ver.nightly = val.equals("true"); - } - if (key.equals("revision")) { - ver.revision = val; - } - if (key.equals("build")) { - ver.build = Integer.parseInt(val); - } - if (key.equals("major")) { - ver.major = Integer.parseInt(val); - } - if (key.equals("minor")) { - ver.minor = Integer.parseInt(val); - } - if (key.equals("release")) { - ver.release = Integer.parseInt(val); - } - if (key.equals("longVersionName")) { - ver.longVersionName = val; - } - if (key.equals("releaseDate")) { - ver.releaseDate = val; - } - if (key.equals("appName")) { - ver.appName = val; - } - if (key.equals("appFullName")) { - ver.appFullName = val; - } - if (key.equals("updateLink")) { - ver.updateLink = val; - } - if (key.equals("change[]")) { - String changeType = val.substring(0, val.indexOf('|')); - String change = val.substring(val.indexOf('|') + 1); - if (!ver.changes.containsKey(changeType)) { - ver.changes.put(changeType, new ArrayList<>()); - } - List chlist = ver.changes.get(changeType); - chlist.add(change); - } - } - } - } - } - - if (!versions.isEmpty()) { - View.execInEventDispatch(() -> { - NewVersionDialog newVersionDialog = new NewVersionDialog(versions); - newVersionDialog.setVisible(true); - Configuration.lastUpdatesCheckDate.set(Calendar.getInstance()); - }); - - return true; - } - } catch (IOException | NumberFormatException ex) { - return false; - } - Configuration.lastUpdatesCheckDate.set(Calendar.getInstance()); - return false; - } - - private static FileHandler fileTxt; - - public static void clearLogFile() { - Logger logger = Logger.getLogger(""); - - FileHandler oldFileTxt = fileTxt; - fileTxt = null; - if (oldFileTxt != null) { - logger.removeHandler(fileTxt); - oldFileTxt.flush(); - oldFileTxt.close(); - } - - String fileName; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss"); - - try { - fileName = Configuration.getFFDecHome() + File.separator + "logs" + File.separator; - if (Configuration.useDetailedLogging.get()) { - fileName += "log-" + sdf.format(new Date()) + ".txt"; - } else { - fileName += "log.txt"; - } - File f = new File(fileName).getParentFile(); - if (!f.exists()) { - f.mkdir(); - } - fileTxt = new FileHandler(fileName); - } catch (IOException | SecurityException ex) { - logger.log(Level.SEVERE, null, ex); - } - - Formatter formatterTxt = new LogFormatter(); - fileTxt.setFormatter(formatterTxt); - logger.addHandler(fileTxt); - - if (!GraphicsEnvironment.isHeadless() && ErrorLogFrame.hasInstance()) { - ErrorLogFrame.getInstance().clearErrorState(); - } - - sdf = new SimpleDateFormat("yyyy-MM-dd"); - logger.log(Level.INFO, "Date: {0}", sdf.format(new Date())); - logger.log(Level.INFO, ApplicationInfo.applicationVerName); - logger.log(Level.INFO, "{0} {1} {2}", new Object[]{ - System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")}); - logger.log(Level.INFO, "{0} {1} {2}", new Object[]{ - System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("os.arch")}); - } - - public static void initLogging(boolean debug) { - try { - Logger logger = Logger.getLogger(""); - logger.setLevel(Configuration.logLevel); - - Handler[] handlers = logger.getHandlers(); - for (int i = handlers.length - 1; i >= 0; i--) { - logger.removeHandler(handlers[i]); - } - - ConsoleHandler conHan = new ConsoleHandler(); - conHan.setLevel(debug ? Level.CONFIG : Level.WARNING); - SimpleFormatter formatterTxt = new SimpleFormatter(); - conHan.setFormatter(formatterTxt); - logger.addHandler(conHan); - clearLogFile(); - - } catch (Exception ex) { - throw new RuntimeException("Problems with creating the log files"); - } - } -} +/* + * Copyright (C) 2010-2015 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.ApplicationInfo; +import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFBundle; +import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.SearchMode; +import com.jpexs.decompiler.flash.SwfOpenException; +import com.jpexs.decompiler.flash.Version; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; +import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; +import com.jpexs.decompiler.flash.console.ContextMenuTools; +import com.jpexs.decompiler.flash.exporters.modes.ExeExportMode; +import com.jpexs.decompiler.flash.gui.pipes.FirstInstance; +import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.helpers.Cache; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.Path; +import com.jpexs.helpers.ProgressListener; +import com.jpexs.helpers.Stopwatch; +import com.jpexs.helpers.streams.SeekableInputStream; +import com.sun.jna.Platform; +import com.sun.jna.platform.win32.Advapi32Util; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinReg; +import java.awt.AWTException; +import java.awt.Frame; +import java.awt.GraphicsEnvironment; +import java.awt.MenuItem; +import java.awt.PopupMenu; +import java.awt.SystemTray; +import java.awt.TrayIcon; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Map.Entry; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.logging.ConsoleHandler; +import java.util.logging.FileHandler; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.SwingWorker; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.filechooser.FileFilter; +import org.pushingpixels.substance.api.SubstanceLookAndFeel; + +/** + * Main executable class + * + * @author JPEXS + */ +public class Main { + + protected static ProxyFrame proxyFrame; + + private static List sourceInfos = new ArrayList<>(); + + public static LoadingDialog loadingDialog; + + private static boolean working = false; + + private static TrayIcon trayIcon; + + private static MenuItem stopMenuItem; + + private static MainFrame mainFrame; + + public static final int UPDATE_SYSTEM_MAJOR = 1; + + public static final int UPDATE_SYSTEM_MINOR = 3; + + private static LoadFromMemoryFrame loadFromMemoryFrame; + + private static LoadFromCacheFrame loadFromCacheFrame; + + private static final Logger logger = Logger.getLogger(Main.class.getName()); + + public static DebugLogDialog debugDialog; + + public static boolean shouldCloseWhenClosingLoadingDialog; + + public static void ensureMainFrame() { + if (mainFrame == null) { + synchronized (Main.class) { + if (mainFrame == null) { + MainFrame frame; + if (Configuration.useRibbonInterface.get()) { + frame = new MainFrameRibbon(); + } else { + frame = new MainFrameClassic(); + } + frame.getPanel().setErrorState(ErrorLogFrame.getInstance().getErrorState()); + mainFrame = frame; + } + } + } + } + + public static MainFrame getMainFrame() { + return mainFrame; + } + + public static void loadFromCache() { + if (loadFromCacheFrame == null) { + loadFromCacheFrame = new LoadFromCacheFrame(); + } + loadFromCacheFrame.setVisible(true); + } + + public static void loadFromMemory() { + if (loadFromMemoryFrame == null) { + loadFromMemoryFrame = new LoadFromMemoryFrame(mainFrame); + } + loadFromMemoryFrame.setVisible(true); + } + + public static void setSubLimiter(boolean value) { + if (value) { + AVM2Code.toSourceLimit = Configuration.sublimiter.get(); + } else { + AVM2Code.toSourceLimit = -1; + } + } + + public static boolean isWorking() { + return working; + } + + public static void startProxy(int port) { + if (proxyFrame == null) { + proxyFrame = new ProxyFrame(mainFrame); + } + + proxyFrame.setPort(port); + addTrayIcon(); + switchProxy(); + } + + public static void showProxy() { + if (proxyFrame == null) { + proxyFrame = new ProxyFrame(mainFrame); + } + proxyFrame.setVisible(true); + proxyFrame.setState(Frame.NORMAL); + } + + public static void startWork(String name) { + startWork(name, -1, null); + } + + public static void startWork(String name, int percent) { + startWork(name, percent, null); + } + + public static void startWork(String name, CancellableWorker worker) { + startWork(name, -1, worker); + } + + public static void startWork(final String name, final int percent, final CancellableWorker worker) { + working = true; + View.execInEventDispatchLater(() -> { + if (mainFrame != null) { + mainFrame.getPanel().setWorkStatus(name, worker); + if (percent == -1) { + mainFrame.getPanel().hidePercent(); + } else { + mainFrame.getPanel().setPercent(percent); + } + } + if (loadingDialog != null) { + loadingDialog.setDetail(name); + loadingDialog.setPercent(percent); + } + if (CommandLineArgumentParser.isCommandLineMode()) { + System.out.println(name); + } + }); + } + + public static void stopWork() { + working = false; + View.execInEventDispatchLater(() -> { + if (mainFrame != null) { + mainFrame.getPanel().setWorkStatus("", null); + } + if (loadingDialog != null) { + loadingDialog.setDetail(""); + } + }); + } + + public static SWFList parseSWF(SWFSourceInfo sourceInfo) throws Exception { + SWFList result = new SWFList(); + + InputStream inputStream = sourceInfo.getInputStream(); + SWFBundle bundle = null; + FileInputStream fis = null; + if (inputStream == null) { + inputStream = new BufferedInputStream(fis = new FileInputStream(sourceInfo.getFile())); + bundle = sourceInfo.getBundle(false, SearchMode.ALL); + logger.log(Level.INFO, "Load file: {0}", sourceInfo.getFile()); + } else if (inputStream instanceof SeekableInputStream + || inputStream instanceof BufferedInputStream) { + try { + inputStream.reset(); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + logger.log(Level.INFO, "Load stream: {0}", sourceInfo.getFileTitle()); + } + + Stopwatch sw = Stopwatch.startNew(); + if (bundle != null) { + result.bundle = bundle; + result.name = new File(sourceInfo.getFileTitleOrName()).getName(); + for (Entry streamEntry : bundle.getAll().entrySet()) { + InputStream stream = streamEntry.getValue(); + stream.reset(); + CancellableWorker worker = new CancellableWorker() { + @Override + public SWF doInBackground() throws Exception { + SWF swf = new SWF(stream, null, streamEntry.getKey(), new ProgressListener() { + @Override + public void progress(int p) { + startWork(AppStrings.translate("work.reading.swf"), p); + } + }, Configuration.parallelSpeedUp.get()); + return swf; + } + }; + loadingDialog.setWroker(worker); + worker.execute(); + + try { + result.add(worker.get()); + } catch (CancellationException ex) { + logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", streamEntry.getKey()); + } + } + } else { + InputStream fInputStream = inputStream; + CancellableWorker worker = new CancellableWorker() { + @Override + public SWF doInBackground() throws Exception { + SWF swf = new SWF(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle(), new ProgressListener() { + @Override + public void progress(int p) { + startWork(AppStrings.translate("work.reading.swf"), p); + } + }, Configuration.parallelSpeedUp.get()); + return swf; + } + }; + if (loadingDialog != null) { + loadingDialog.setWroker(worker); + } + worker.execute(); + + try { + result.add(worker.get()); + } catch (CancellationException ex) { + logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", sourceInfo.getFileTitleOrName()); + } + } + + if (fis != null) { + logger.log(Level.INFO, "File loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000)); + fis.close(); + } else { + logger.log(Level.INFO, "Stream loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000)); + } + + result.sourceInfo = sourceInfo; + for (SWF swf : result) { + logger.log(Level.INFO, ""); + logger.log(Level.INFO, "== File information =="); + logger.log(Level.INFO, "Size: {0}", Helper.formatFileSize(swf.fileSize)); + logger.log(Level.INFO, "Flash version: {0}", swf.version); + int width = (int) ((swf.displayRect.Xmax - swf.displayRect.Xmin) / SWF.unitDivisor); + int height = (int) ((swf.displayRect.Ymax - swf.displayRect.Ymin) / SWF.unitDivisor); + logger.log(Level.INFO, "Width: {0}", width); + logger.log(Level.INFO, "Height: {0}", height); + + swf.swfList = result; + swf.addEventListener(new EventListener() { + @Override + public void handleExportingEvent(String type, int index, int count, Object data) { + String text = AppStrings.translate("work.exporting"); + if (type != null && type.length() > 0) { + text += " " + type; + } + + startWork(text + " " + index + "/" + count + " " + data); + } + + @Override + public void handleExportedEvent(String type, int index, int count, Object data) { + String text = AppStrings.translate("work.exported"); + if (type != null && type.length() > 0) { + text += " " + type; + } + + startWork(text + " " + index + "/" + count + " " + data); + } + + @Override + public void handleEvent(String event, Object data) { + if (event.equals("exporting") || event.equals("exported")) { + throw new Error("Event is not supported by this handler."); + } + if (event.equals("getVariables")) { + startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); + } + if (event.equals("deobfuscate")) { + startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); + } + if (event.equals("rename")) { + startWork(AppStrings.translate("work.renaming") + "..." + (String) data); + } + } + }); + } + + return result; + } + + public static void saveFile(SWF swf, String outfile) throws IOException { + saveFile(swf, outfile, SaveFileMode.SAVE, null); + } + + public static void saveFile(SWF swf, String outfile, SaveFileMode mode, ExeExportMode exeExportMode) throws IOException { + if (mode == SaveFileMode.SAVEAS && !swf.swfList.isBundle()) { + swf.setFile(outfile); + swf.swfList.sourceInfo.setFile(outfile); + } + File outfileF = new File(outfile); + File tmpFile = new File(outfile + ".tmp"); + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(tmpFile))) { + if (mode == SaveFileMode.EXE) { + switch (exeExportMode) { + case WRAPPER: + InputStream exeStream = View.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/Swf2Exe.bin"); + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = exeStream.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); + } + int width = swf.displayRect.Xmax - swf.displayRect.Xmin; + int height = swf.displayRect.Ymax - swf.displayRect.Ymin; + fos.write(width & 0xff); + fos.write((width >> 8) & 0xff); + fos.write((width >> 16) & 0xff); + fos.write((width >> 24) & 0xff); + fos.write(height & 0xff); + fos.write((height >> 8) & 0xff); + fos.write((height >> 16) & 0xff); + fos.write((height >> 24) & 0xff); + fos.write(Configuration.saveAsExeScaleMode.get()); + break; + case PROJECTOR_WIN: + // todo + break; + case PROJECTOR_MAC: + // todo + break; + } + } + swf.saveTo(fos); + } + if (tmpFile.exists()) { + if (tmpFile.length() > 0) { + outfileF.delete(); + if (!tmpFile.renameTo(outfileF)) { + tmpFile.delete(); + throw new IOException("Cannot access " + outfile); + } + } else { + throw new IOException("Output is empty"); + } + } + } + + private static class OpenFileWorker extends SwingWorker { + + private final SWFSourceInfo[] sourceInfos; + + private final Runnable executeAfterOpen; + + public OpenFileWorker(SWFSourceInfo sourceInfo) { + this(sourceInfo, null); + } + + public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { + this.sourceInfos = new SWFSourceInfo[]{sourceInfo}; + this.executeAfterOpen = executeAfterOpen; + } + + public OpenFileWorker(SWFSourceInfo[] sourceInfos) { + this(sourceInfos, null); + } + + public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen) { + this.sourceInfos = sourceInfos; + this.executeAfterOpen = executeAfterOpen; + } + + @Override + protected Object doInBackground() throws Exception { + boolean first = true; + SWF firstSWF = null; + for (final SWFSourceInfo sourceInfo : sourceInfos) { + SWFList swfs = null; + try { + Main.startWork(AppStrings.translate("work.reading.swf") + "..."); + try { + swfs = parseSWF(sourceInfo); + } catch (ExecutionException ex) { + Throwable cause = ex.getCause(); + if (cause instanceof SwfOpenException) { + throw (SwfOpenException) cause; + } + + throw ex; + } + } catch (OutOfMemoryError ex) { + logger.log(Level.SEVERE, null, ex); + View.showMessageDialog(null, "Cannot load SWF file. Out of memory."); + continue; + } catch (SwfOpenException ex) { + logger.log(Level.SEVERE, null, ex); + View.showMessageDialog(null, ex.getMessage()); + continue; + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + View.showMessageDialog(null, "Cannot load SWF file."); + continue; + } + + final SWFList swfs1 = swfs; + final boolean first1 = first; + first = false; + if (firstSWF == null) { + firstSWF = swfs1.get(0); + } + + try { + View.execInEventDispatch(() -> { + Main.startWork(AppStrings.translate("work.creatingwindow") + "..."); + ensureMainFrame(); + mainFrame.getPanel().load(swfs1, first1); + }); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + loadingDialog.setVisible(false); + shouldCloseWhenClosingLoadingDialog = false; + + final SWF fswf = firstSWF; + View.execInEventDispatch(() -> { + if (mainFrame != null) { + mainFrame.setVisible(true); + } + + Main.stopWork(); + + if (mainFrame != null && Configuration.gotoMainClassOnStartup.get()) { + mainFrame.getPanel().gotoDocumentClass(fswf); + } + + if (mainFrame != null && fswf != null) { + SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(fswf.getShortFileName()); + if (swfConf != null) { + String pathStr = swfConf.lastSelectedPath; + mainFrame.getPanel().tagTree.setSelectionPathString(pathStr); + } + } + + if (executeAfterOpen != null) { + executeAfterOpen.run(); + } + }); + + return true; + } + } + + public static boolean reloadSWFs() { + CancellableWorker.cancelBackgroundThreads(); + if (Main.sourceInfos.isEmpty()) { + Helper.freeMem(); + showModeFrame(); + return true; + } else { + SWFSourceInfo[] sourceInfosCopy = new SWFSourceInfo[sourceInfos.size()]; + sourceInfos.toArray(sourceInfosCopy); + sourceInfos.clear(); + openFile(sourceInfosCopy); + return true; + } + } + + public static void reloadApp() { + if (debugDialog != null) { + debugDialog.setVisible(false); + debugDialog.dispose(); + debugDialog = null; + } + if (loadingDialog != null) { + synchronized (Main.class) { + if (loadingDialog != null) { + loadingDialog.setVisible(false); + loadingDialog.dispose(); + loadingDialog = null; + } + } + } + if (proxyFrame != null) { + proxyFrame.setVisible(false); + proxyFrame.dispose(); + proxyFrame = null; + } + if (loadFromMemoryFrame != null) { + loadFromMemoryFrame.setVisible(false); + loadFromMemoryFrame.dispose(); + loadFromMemoryFrame = null; + } + if (loadFromCacheFrame != null) { + loadFromCacheFrame.setVisible(false); + loadFromCacheFrame.dispose(); + loadFromCacheFrame = null; + } + if (mainFrame != null) { + mainFrame.setVisible(false); + mainFrame.getPanel().closeAll(); + mainFrame.dispose(); + mainFrame = null; + } + FontTag.reload(); + Cache.clearAll(); + initGui(); + reloadSWFs(); + } + + public static OpenFileResult openFile(String swfFile, String fileTitle) { + return openFile(swfFile, fileTitle, null); + } + + public static OpenFileResult openFile(String swfFile, String fileTitle, Runnable executeAfterOpen) { + try { + File file = new File(swfFile); + if (!file.exists()) { + View.showMessageDialog(null, AppStrings.translate("open.error.fileNotFound"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); + return OpenFileResult.NOT_FOUND; + } + swfFile = file.getCanonicalPath(); + Configuration.addRecentFile(swfFile); + SWFSourceInfo sourceInfo = new SWFSourceInfo(null, swfFile, fileTitle); + OpenFileResult openResult = openFile(sourceInfo); + return openResult; + } catch (IOException ex) { + View.showMessageDialog(null, AppStrings.translate("open.error.cannotOpen"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); + return OpenFileResult.ERROR; + } + } + + public static OpenFileResult openFile(SWFSourceInfo sourceInfo) { + return openFile(new SWFSourceInfo[]{sourceInfo}); + } + + public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { + return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen); + } + + public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos) { + return openFile(newSourceInfos, null); + } + + public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen) { + if (mainFrame != null && !Configuration.openMultipleFiles.get()) { + sourceInfos.clear(); + mainFrame.getPanel().closeAll(); + mainFrame.setVisible(false); + Helper.freeMem(); + } + + loadingDialog.setVisible(true); + OpenFileWorker wrk = new OpenFileWorker(newSourceInfos, executeAfterOpen); + wrk.execute(); + sourceInfos.addAll(Arrays.asList(newSourceInfos)); + return OpenFileResult.OK; + } + + public static void closeFile(SWFList swf) { + sourceInfos.remove(swf.sourceInfo); + mainFrame.getPanel().close(swf); + } + + public static void closeAll() { + sourceInfos.clear(); + mainFrame.getPanel().closeAll(); + } + + public static boolean saveFileDialog(SWF swf, final SaveFileMode mode) { + JFileChooser fc = new JFileChooser(); + fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get())); + String ext = ".swf"; + switch (mode) { + case SAVE: + case SAVEAS: + if (swf.getFile() != null) { + ext = Path.getExtension(swf.getFile()); + } + break; + case EXE: + ext = ".exe"; + break; + } + + FileFilter swfFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.swf"); + } + }; + + FileFilter gfxFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.gfx"); + } + }; + + ExeExportMode exeExportMode = null; + if (mode == SaveFileMode.EXE) { + exeExportMode = Configuration.exeExportMode.get(); + String filterDescription = null; + switch (exeExportMode) { + case WRAPPER: + ext = ".exe"; + filterDescription = "filter.exe"; + break; + case PROJECTOR_WIN: + ext = ".exe"; + filterDescription = "filter.exe"; + break; + case PROJECTOR_MAC: + ext = ".dmg"; + filterDescription = "filter.dmg"; + break; + /*case PROJECTOR_LINUX: + // linux projector is compressed with tar.gz + // todo: decompress + ext = ""; + filterDescription = "filter.linuxExe"; + break;*/ + } + + String fext = ext; + String ffilterDescription = filterDescription; + FileFilter exeFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(fext)) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate(ffilterDescription); + } + }; + fc.setFileFilter(exeFilter); + } else { + if (swf.gfx) { + fc.addChoosableFileFilter(swfFilter); + fc.setFileFilter(gfxFilter); + } else { + fc.setFileFilter(swfFilter); + fc.addChoosableFileFilter(gfxFilter); + } + } + final String extension = ext; + fc.setAcceptAllFileFilterUsed(false); + JFrame f = new JFrame(); + View.setWindowIcon(f); + if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) { + File file = Helper.fixDialogFile(fc.getSelectedFile()); + FileFilter selFilter = fc.getFileFilter(); + try { + String fileName = file.getAbsolutePath(); + if (selFilter == swfFilter) { + if (!fileName.toLowerCase().endsWith(extension)) { + fileName += extension; + } + swf.gfx = false; + } + if (selFilter == gfxFilter) { + if (!fileName.toLowerCase().endsWith(".gfx")) { + fileName += ".gfx"; + } + swf.gfx = true; + } + Main.saveFile(swf, fileName, mode, exeExportMode); + Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath()); + return true; + } catch (IOException ex) { + View.showMessageDialog(null, AppStrings.translate("error.file.write")); + } + } + return false; + } + + public static boolean openFileDialog() { + JFileChooser fc = new JFileChooser(); + if (Configuration.openMultipleFiles.get()) { + fc.setMultiSelectionEnabled(true); + } + fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); + FileFilter allSupportedFilter = new FileFilter() { + private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip"}; + + @Override + public boolean accept(File f) { + String name = f.getName().toLowerCase(); + for (String ext : supportedExtensions) { + if (name.endsWith(ext)) { + return true; + } + } + return f.isDirectory(); + } + + @Override + public String getDescription() { + String exts = Helper.joinStrings(supportedExtensions, "*%s", "; "); + return AppStrings.translate("filter.supported") + " (" + exts + ")"; + } + }; + fc.setFileFilter(allSupportedFilter); + FileFilter swfFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.swf"); + } + }; + fc.addChoosableFileFilter(swfFilter); + + FileFilter swcFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".swc")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.swc"); + } + }; + fc.addChoosableFileFilter(swcFilter); + + FileFilter gfxFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.gfx"); + } + }; + fc.addChoosableFileFilter(gfxFilter); + + FileFilter zipFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".zip")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.zip"); + } + }; + fc.addChoosableFileFilter(zipFilter); + + FileFilter binaryFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return true; + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.binary"); + } + }; + fc.addChoosableFileFilter(binaryFilter); + + fc.setAcceptAllFileFilterUsed(false); + JFrame f = new JFrame(); + View.setWindowIcon(f); + int returnVal = fc.showOpenDialog(f); + if (returnVal == JFileChooser.APPROVE_OPTION) { + Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); + File[] selFiles = fc.getSelectedFiles(); + for (File file : selFiles) { + File selfile = Helper.fixDialogFile(file); + Main.openFile(selfile.getAbsolutePath(), null); + } + return true; + } else { + return false; + } + } + + public static void displayErrorFrame() { + ErrorLogFrame.getInstance().setVisible(true); + } + + private static void initGui() { + if (GraphicsEnvironment.isHeadless()) { + System.err.println("Error: Your system does not support Graphic User Interface"); + exit(); + } + if (Configuration.useRibbonInterface.get()) { + View.setLookAndFeel(); + } else { + try { + UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, null); + UIManager.put("Tree.expandedIcon", null); + UIManager.put("Tree.collapsedIcon", null); + UIManager.put("ColorChooserUI", null); + UIManager.put("ColorChooser.swatchesRecentSwatchSize", null); + UIManager.put("ColorChooser.swatchesSwatchSize", null); + UIManager.put("RibbonApplicationMenuPopupPanelUI", null); + UIManager.put("RibbonApplicationMenuButtonUI", null); + UIManager.put("ProgressBarUI", null); + UIManager.put("TextField.background", null); + UIManager.put("FormattedTextField.background", null); + UIManager.put("CommandButtonUI", null); + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + ErrorLogFrame.createNewInstance(); + + autoCheckForUpdates(); + offerAssociation(); + loadingDialog = new LoadingDialog(); + } + + public static void showModeFrame() { + ensureMainFrame(); + mainFrame.setVisible(true); + } + + private static void offerAssociation() { + boolean offered = Configuration.offeredAssociation.get(); + if (!offered) { + if (Platform.isWindows()) { + if ((!ContextMenuTools.isAddedToContextMenu()) && View.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { + ContextMenuTools.addToContextMenu(true, false); + } + } + + Configuration.offeredAssociation.set(true); + } + } + + public static void initLang() { + if (GraphicsEnvironment.isHeadless()) { //No GUI in OS + return; + } + if (!Configuration.locale.hasValue()) { + if (Platform.isWindows()) { + //Load from Installer + String uninstKey = "{E618D276-6596-41F4-8A98-447D442A77DB}_is1"; + uninstKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uninstKey; + try { + if (Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey)) { + if (Advapi32Util.registryValueExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language")) { + String installedLoc = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language"); + int lcid = Integer.parseInt(installedLoc); + char buf[] = new char[9]; + int cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO639LANGNAME, buf, 9); + String langCode = new String(buf, 0, cnt).trim().toLowerCase(); + + cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO3166CTRYNAME, buf, 9); + String countryCode = new String(buf, 0, cnt).trim().toLowerCase(); + + List langs = Arrays.asList(SelectLanguageDialog.getAvailableLanguages()); + for (int i = 0; i < langs.size(); i++) { + langs.set(i, langs.get(i).toLowerCase()); + } + + String selectedLang = null; + + if (langs.contains(langCode + "-" + countryCode)) { + selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode + "-" + countryCode)]; + } else if (langs.contains(langCode)) { + selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode)]; + } + if (selectedLang != null) { + Configuration.locale.set(selectedLang); + } + } + } + } catch (Exception ex) { + //ignore + } + } + } + Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get())); + AppStrings.updateLanguage(); + + try { + Class cl = Class.forName("org.pushingpixels.substance.api.SubstanceLookAndFeel"); + Field field = cl.getDeclaredField("LABEL_BUNDLE"); + field.setAccessible(true); + field.set(null, null); + } catch (Throwable ex) { + logger.log(Level.SEVERE, null, ex); + } + + UIManager.put("OptionPane.okButtonText", AppStrings.translate("button.ok")); + UIManager.put("OptionPane.yesButtonText", AppStrings.translate("button.yes")); + UIManager.put("OptionPane.noButtonText", AppStrings.translate("button.no")); + UIManager.put("OptionPane.cancelButtonText", AppStrings.translate("button.cancel")); + UIManager.put("OptionPane.messageDialogTitle", AppStrings.translate("dialog.message.title")); + UIManager.put("OptionPane.titleText", AppStrings.translate("dialog.select.title")); + + UIManager.put("FileChooser.acceptAllFileFilterText", AppStrings.translate("FileChooser.acceptAllFileFilterText")); + UIManager.put("FileChooser.lookInLabelText", AppStrings.translate("FileChooser.lookInLabelText")); + UIManager.put("FileChooser.cancelButtonText", AppStrings.translate("button.cancel")); + UIManager.put("FileChooser.cancelButtonToolTipText", AppStrings.translate("button.cancel")); + UIManager.put("FileChooser.openButtonText", AppStrings.translate("FileChooser.openButtonText")); + UIManager.put("FileChooser.openButtonToolTipText", AppStrings.translate("FileChooser.openButtonToolTipText")); + UIManager.put("FileChooser.filesOfTypeLabelText", AppStrings.translate("FileChooser.filesOfTypeLabelText")); + UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); + UIManager.put("FileChooser.listViewButtonToolTipText", AppStrings.translate("FileChooser.listViewButtonToolTipText")); + UIManager.put("FileChooser.listViewButtonAccessibleName", AppStrings.translate("FileChooser.listViewButtonAccessibleName")); + UIManager.put("FileChooser.detailsViewButtonToolTipText", AppStrings.translate("FileChooser.detailsViewButtonToolTipText")); + UIManager.put("FileChooser.detailsViewButtonAccessibleName", AppStrings.translate("FileChooser.detailsViewButtonAccessibleName")); + UIManager.put("FileChooser.upFolderToolTipText", AppStrings.translate("FileChooser.upFolderToolTipText")); + UIManager.put("FileChooser.upFolderAccessibleName", AppStrings.translate("FileChooser.upFolderAccessibleName")); + UIManager.put("FileChooser.homeFolderToolTipText", AppStrings.translate("FileChooser.homeFolderToolTipText")); + UIManager.put("FileChooser.homeFolderAccessibleName", AppStrings.translate("FileChooser.homeFolderAccessibleName")); + UIManager.put("FileChooser.fileNameHeaderText", AppStrings.translate("FileChooser.fileNameHeaderText")); + UIManager.put("FileChooser.fileSizeHeaderText", AppStrings.translate("FileChooser.fileSizeHeaderText")); + UIManager.put("FileChooser.fileTypeHeaderText", AppStrings.translate("FileChooser.fileTypeHeaderText")); + UIManager.put("FileChooser.fileDateHeaderText", AppStrings.translate("FileChooser.fileDateHeaderText")); + UIManager.put("FileChooser.fileAttrHeaderText", AppStrings.translate("FileChooser.fileAttrHeaderText")); + UIManager.put("FileChooser.openDialogTitleText", AppStrings.translate("FileChooser.openDialogTitleText")); + UIManager.put("FileChooser.directoryDescriptionText", AppStrings.translate("FileChooser.directoryDescriptionText")); + UIManager.put("FileChooser.directoryOpenButtonText", AppStrings.translate("FileChooser.directoryOpenButtonText")); + UIManager.put("FileChooser.directoryOpenButtonToolTipText", AppStrings.translate("FileChooser.directoryOpenButtonToolTipText")); + UIManager.put("FileChooser.fileDescriptionText", AppStrings.translate("FileChooser.fileDescriptionText")); + UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); + UIManager.put("FileChooser.helpButtonText", AppStrings.translate("FileChooser.helpButtonText")); + UIManager.put("FileChooser.helpButtonToolTipText", AppStrings.translate("FileChooser.helpButtonToolTipText")); + UIManager.put("FileChooser.newFolderAccessibleName", AppStrings.translate("FileChooser.newFolderAccessibleName")); + UIManager.put("FileChooser.newFolderErrorText", AppStrings.translate("FileChooser.newFolderErrorText")); + UIManager.put("FileChooser.newFolderToolTipText", AppStrings.translate("FileChooser.newFolderToolTipText")); + UIManager.put("FileChooser.other.newFolder", AppStrings.translate("FileChooser.other.newFolder")); + UIManager.put("FileChooser.other.newFolder.subsequent", AppStrings.translate("FileChooser.other.newFolder.subsequent")); + UIManager.put("FileChooser.win32.newFolder", AppStrings.translate("FileChooser.win32.newFolder")); + UIManager.put("FileChooser.win32.newFolder.subsequent", AppStrings.translate("FileChooser.win32.newFolder.subsequent")); + UIManager.put("FileChooser.saveButtonText", AppStrings.translate("FileChooser.saveButtonText")); + UIManager.put("FileChooser.saveButtonToolTipText", AppStrings.translate("FileChooser.saveButtonToolTipText")); + UIManager.put("FileChooser.saveDialogTitleText", AppStrings.translate("FileChooser.saveDialogTitleText")); + UIManager.put("FileChooser.saveInLabelText", AppStrings.translate("FileChooser.saveInLabelText")); + UIManager.put("FileChooser.updateButtonText", AppStrings.translate("FileChooser.updateButtonText")); + UIManager.put("FileChooser.updateButtonToolTipText", AppStrings.translate("FileChooser.updateButtonToolTipText")); + + UIManager.put("FileChooser.detailsViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewActionLabel.textAndMnemonic")); + UIManager.put("FileChooser.detailsViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewButtonToolTip.textAndMnemonic")); + UIManager.put("FileChooser.fileAttrHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileAttrHeader.textAndMnemonic")); + UIManager.put("FileChooser.fileDateHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileDateHeader.textAndMnemonic")); + UIManager.put("FileChooser.fileNameHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileNameHeader.textAndMnemonic")); + UIManager.put("FileChooser.fileNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.fileNameLabel.textAndMnemonic")); + UIManager.put("FileChooser.fileSizeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileSizeHeader.textAndMnemonic")); + UIManager.put("FileChooser.fileTypeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileTypeHeader.textAndMnemonic")); + UIManager.put("FileChooser.filesOfTypeLabel.textAndMnemonic", AppStrings.translate("FileChooser.filesOfTypeLabel.textAndMnemonic")); + UIManager.put("FileChooser.folderNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.folderNameLabel.textAndMnemonic")); + UIManager.put("FileChooser.homeFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.homeFolderToolTip.textAndMnemonic")); + UIManager.put("FileChooser.listViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.listViewActionLabel.textAndMnemonic")); + UIManager.put("FileChooser.listViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.listViewButtonToolTip.textAndMnemonic")); + UIManager.put("FileChooser.lookInLabel.textAndMnemonic", AppStrings.translate("FileChooser.lookInLabel.textAndMnemonic")); + UIManager.put("FileChooser.newFolderActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.newFolderActionLabel.textAndMnemonic")); + UIManager.put("FileChooser.newFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.newFolderToolTip.textAndMnemonic")); + UIManager.put("FileChooser.refreshActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.refreshActionLabel.textAndMnemonic")); + UIManager.put("FileChooser.saveInLabel.textAndMnemonic", AppStrings.translate("FileChooser.saveInLabel.textAndMnemonic")); + UIManager.put("FileChooser.upFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.upFolderToolTip.textAndMnemonic")); + UIManager.put("FileChooser.viewMenuButtonAccessibleName", AppStrings.translate("FileChooser.viewMenuButtonAccessibleName")); + UIManager.put("FileChooser.viewMenuButtonToolTipText", AppStrings.translate("FileChooser.viewMenuButtonToolTipText")); + UIManager.put("FileChooser.viewMenuLabel.textAndMnemonic", AppStrings.translate("FileChooser.viewMenuLabel.textAndMnemonic")); + UIManager.put("FileChooser.newFolderActionLabelText", AppStrings.translate("FileChooser.newFolderActionLabelText")); + UIManager.put("FileChooser.listViewActionLabelText", AppStrings.translate("FileChooser.listViewActionLabelText")); + UIManager.put("FileChooser.detailsViewActionLabelText", AppStrings.translate("FileChooser.detailsViewActionLabelText")); + UIManager.put("FileChooser.refreshActionLabelText", AppStrings.translate("FileChooser.refreshActionLabelText")); + UIManager.put("FileChooser.sortMenuLabelText", AppStrings.translate("FileChooser.sortMenuLabelText")); + UIManager.put("FileChooser.viewMenuLabelText", AppStrings.translate("FileChooser.viewMenuLabelText")); + UIManager.put("FileChooser.fileSizeKiloBytes", AppStrings.translate("FileChooser.fileSizeKiloBytes")); + UIManager.put("FileChooser.fileSizeMegaBytes", AppStrings.translate("FileChooser.fileSizeMegaBytes")); + UIManager.put("FileChooser.fileSizeGigaBytes", AppStrings.translate("FileChooser.fileSizeGigaBytes")); + UIManager.put("FileChooser.folderNameLabelText", AppStrings.translate("FileChooser.folderNameLabelText")); + + UIManager.put("ColorChooser.okText", AppStrings.translate("ColorChooser.okText")); + UIManager.put("ColorChooser.cancelText", AppStrings.translate("ColorChooser.cancelText")); + UIManager.put("ColorChooser.resetText", AppStrings.translate("ColorChooser.resetText")); + UIManager.put("ColorChooser.previewText", AppStrings.translate("ColorChooser.previewText")); + UIManager.put("ColorChooser.swatchesNameText", AppStrings.translate("ColorChooser.swatchesNameText")); + UIManager.put("ColorChooser.swatchesRecentText", AppStrings.translate("ColorChooser.swatchesRecentText")); + UIManager.put("ColorChooser.sampleText", AppStrings.translate("ColorChooser.sampleText")); + + Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable"); + } + + /** + * Clear old FFDec/JavactiveX temp files + */ + private static void clearTemp() { + String tempDirPath = System.getProperty("java.io.tmpdir"); + if (tempDirPath == null) { + return; + } + File tempDir = new File(tempDirPath); + if (!tempDir.exists()) { + return; + } + File delFiles[] = tempDir.listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return name.matches("ffdec_cache.*\\.tmp") || name.matches("javactivex_.*\\.exe") || name.matches("temp[0-9]+\\.swf") || name.matches("ffdec_view_.*\\.swf"); + } + }); + for (File f : delFiles) { + try { + f.delete(); + } catch (Exception ex) { + //ignore + } + } + } + + /** + * @param args the command line arguments + * @throws IOException On error + */ + public static void main(String[] args) throws IOException { + + clearTemp(); + String pluginPath = Configuration.pluginPath.get(); + if (pluginPath != null && !pluginPath.isEmpty()) { + try { + SWFDecompilerPlugin.loadPlugin(pluginPath); + } catch (Throwable e) { + View.showMessageDialog(null, "Failed to load plugin: " + pluginPath); + } + } + + AppStrings.setResourceClass(MainFrame.class); + initLogging(Configuration.debugMode.get()); + initLang(); + + if (Configuration.cacheOnDisk.get()) { + Cache.setStorageType(Cache.STORAGE_FILES); + } else { + Cache.setStorageType(Cache.STORAGE_MEMORY); + } + + if (args.length == 0) { + View.execInEventDispatch(() -> { + initGui(); + if (Configuration.allowOnlyOneInstance.get() && FirstInstance.focus()) { //Try to focus first instance + Main.exit(); + } else { + showModeFrame(); + reloadLastSession(); + } + }); + } else { + String[] filesToOpen = CommandLineArgumentParser.parseArguments(args); + if (filesToOpen != null && filesToOpen.length > 0) { + View.execInEventDispatch(() -> { + initGui(); + shouldCloseWhenClosingLoadingDialog = true; + if (Configuration.allowOnlyOneInstance.get() && FirstInstance.openFiles(Arrays.asList(filesToOpen))) { //Try to open in first instance + Main.exit(); + } else { + for (String fileToOpen : filesToOpen) { + openFile(fileToOpen, null); + } + } + }); + } + } + } + + private static void reloadLastSession() { + if (Configuration.saveSessionOnExit.get()) { + String lastSession = Configuration.lastSessionFiles.get(); + if (lastSession != null && lastSession.length() > 0) { + String[] filesToOpen = lastSession.split(File.pathSeparator, -1); + List exfiles = new ArrayList<>(); + for (int i = 0; i < filesToOpen.length; i++) { + if (new File(filesToOpen[i]).exists()) { + exfiles.add(filesToOpen[i]); + } + } + SWFSourceInfo[] sourceInfos = new SWFSourceInfo[exfiles.size()]; + for (int i = 0; i < exfiles.size(); i++) { + sourceInfos[i] = new SWFSourceInfo(null, exfiles.get(i), null); + } + if (sourceInfos.length > 0) { + openFile(sourceInfos, () -> { + mainFrame.getPanel().tagTree.setSelectionPathString(Configuration.lastSessionSelection.get()); + }); + } + } + } + } + + public static String tempFile(String url) throws IOException { + File f = new File(Configuration.getFFDecHome() + "saved" + File.separator); + Path.createDirectorySafe(f); + return Configuration.getFFDecHome() + "saved" + File.separator + "asdec_" + Integer.toHexString(url.hashCode()) + ".tmp"; + } + + public static void removeTrayIcon() { + if (SystemTray.isSupported()) { + SystemTray tray = SystemTray.getSystemTray(); + if (trayIcon != null) { + tray.remove(trayIcon); + trayIcon = null; + } + } + } + + public static void switchProxy() { + proxyFrame.switchState(); + if (stopMenuItem != null) { + if (proxyFrame.isRunning()) { + stopMenuItem.setLabel(AppStrings.translate("proxy.stop")); + } else { + stopMenuItem.setLabel(AppStrings.translate("proxy.start")); + } + } + } + + public static void addTrayIcon() { + if (trayIcon != null) { + return; + } + if (SystemTray.isSupported()) { + SystemTray tray = SystemTray.getSystemTray(); + trayIcon = new TrayIcon(View.loadImage("proxy16"), ApplicationInfo.VENDOR + " " + ApplicationInfo.SHORT_APPLICATION_NAME + " " + AppStrings.translate("proxy")); + trayIcon.setImageAutoSize(true); + PopupMenu trayPopup = new PopupMenu(); + + ActionListener trayListener = new ActionListener() { + /** + * Invoked when an action occurs. + */ + @Override + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("EXIT")) { + Main.exit(); + } + if (e.getActionCommand().equals("SHOW")) { + Main.showProxy(); + } + if (e.getActionCommand().equals("SWITCH")) { + Main.switchProxy(); + } + } + }; + + MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show")); + showMenuItem.setActionCommand("SHOW"); + showMenuItem.addActionListener(trayListener); + trayPopup.add(showMenuItem); + stopMenuItem = new MenuItem(AppStrings.translate("proxy.start")); + stopMenuItem.setActionCommand("SWITCH"); + stopMenuItem.addActionListener(trayListener); + trayPopup.add(stopMenuItem); + trayPopup.addSeparator(); + MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit")); + exitMenuItem.setActionCommand("EXIT"); + exitMenuItem.addActionListener(trayListener); + trayPopup.add(exitMenuItem); + + trayIcon.setPopupMenu(trayPopup); + trayIcon.addMouseListener(new MouseAdapter() { + /** + * {@inheritDoc} + */ + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1) { + Main.showProxy(); + } + } + }); + try { + tray.add(trayIcon); + } catch (AWTException ex) { + } + } + } + + public static void exit() { + Configuration.saveConfig(); + if (mainFrame != null && mainFrame.getPanel() != null) { + mainFrame.getPanel().unloadFlashPlayer(); + } + System.exit(0); + } + + public static void about() { + (new AboutDialog()).setVisible(true); + } + + public static void advancedSettings() { + (new AdvancedSettingsDialog()).setVisible(true); + } + + public static void autoCheckForUpdates() { + if (Configuration.checkForUpdatesAuto.get()) { + Calendar lastUpdatesCheckDate = Configuration.lastUpdatesCheckDate.get(); + if ((lastUpdatesCheckDate == null) || (lastUpdatesCheckDate.getTime().getTime() < Calendar.getInstance().getTime().getTime() - Configuration.checkForUpdatesDelay.get())) { + new SwingWorker() { + @Override + protected Object doInBackground() throws Exception { + checkForUpdates(); + return null; + } + }.execute(); + } + } + } + + public static boolean checkForUpdates() { + String currentVersion = ApplicationInfo.version; + if (currentVersion.equals("unknown")) { + // sometimes during development the version information is not available + return false; + } + + List accepted = new ArrayList<>(); + if (Configuration.checkForUpdatesStable.get()) { + accepted.add("stable"); + } + if (Configuration.checkForUpdatesNightly.get()) { + accepted.add("nightly"); + } + + if (accepted.isEmpty()) { + return false; + } + + String acceptVersions = String.join(",", accepted); + try { + String proxyAddress = Configuration.updateProxyAddress.get(); + URL url = new URL(ApplicationInfo.updateCheckUrl); + + URLConnection uc = null; + if (proxyAddress != null && !proxyAddress.isEmpty()) { + int port = 8080; + if (proxyAddress.contains(":")) { + String[] parts = proxyAddress.split(":"); + port = Integer.parseInt(parts[1]); + proxyAddress = parts[0]; + } + + uc = url.openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, port))); + } else { + uc = url.openConnection(); + } + uc.setRequestProperty("X-Accept-Versions", acceptVersions); + uc.setRequestProperty("X-Update-Major", "" + UPDATE_SYSTEM_MAJOR); + uc.setRequestProperty("X-Update-Minor", "" + UPDATE_SYSTEM_MINOR); + uc.setRequestProperty("User-Agent", ApplicationInfo.shortApplicationVerName); + String currentLoc = Configuration.locale.get("en"); + uc.setRequestProperty("Accept-Language", currentLoc + ("en".equals(currentLoc) ? "" : ", en;q=0.8")); + + uc.connect(); + + BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream())); + String s; + final java.util.List versions = new ArrayList<>(); + String header = ""; + Pattern headerPat = Pattern.compile("\\[([a-zA-Z0-9]+)\\]"); + int updateMajor; + int updateMinor; + Version ver = null; + while ((s = br.readLine()) != null) { + + Matcher m = headerPat.matcher(s); + if (m.matches()) { + header = m.group(1); + if (header.equals("version")) { + ver = new Version(); + versions.add(ver); + } + if (header.equals("noversion")) { + break; + } + } else { + if (s.contains("=")) { + String key = s.substring(0, s.indexOf('=')); + String val = s.substring(s.indexOf('=') + 1); + if ("updateSystem".equals(header)) { + if (key.equals("majorVersion")) { + updateMajor = Integer.parseInt(val); + if (updateMajor > UPDATE_SYSTEM_MAJOR) { + break; + } + } + if (key.equals("minorVersion")) { + updateMinor = Integer.parseInt(val); + } + } + if ("version".equals(header) && (ver != null)) { + if (key.equals("versionId")) { + ver.versionId = Integer.parseInt(val); + } + if (key.equals("versionName")) { + ver.versionName = val; + } + if (key.equals("nightly")) { + ver.nightly = val.equals("true"); + } + if (key.equals("revision")) { + ver.revision = val; + } + if (key.equals("build")) { + ver.build = Integer.parseInt(val); + } + if (key.equals("major")) { + ver.major = Integer.parseInt(val); + } + if (key.equals("minor")) { + ver.minor = Integer.parseInt(val); + } + if (key.equals("release")) { + ver.release = Integer.parseInt(val); + } + if (key.equals("longVersionName")) { + ver.longVersionName = val; + } + if (key.equals("releaseDate")) { + ver.releaseDate = val; + } + if (key.equals("appName")) { + ver.appName = val; + } + if (key.equals("appFullName")) { + ver.appFullName = val; + } + if (key.equals("updateLink")) { + ver.updateLink = val; + } + if (key.equals("change[]")) { + String changeType = val.substring(0, val.indexOf('|')); + String change = val.substring(val.indexOf('|') + 1); + if (!ver.changes.containsKey(changeType)) { + ver.changes.put(changeType, new ArrayList<>()); + } + List chlist = ver.changes.get(changeType); + chlist.add(change); + } + } + } + } + } + + if (!versions.isEmpty()) { + View.execInEventDispatch(() -> { + NewVersionDialog newVersionDialog = new NewVersionDialog(versions); + newVersionDialog.setVisible(true); + Configuration.lastUpdatesCheckDate.set(Calendar.getInstance()); + }); + + return true; + } + } catch (IOException | NumberFormatException ex) { + return false; + } + Configuration.lastUpdatesCheckDate.set(Calendar.getInstance()); + return false; + } + + private static FileHandler fileTxt; + + public static void clearLogFile() { + Logger logger = Logger.getLogger(""); + + FileHandler oldFileTxt = fileTxt; + fileTxt = null; + if (oldFileTxt != null) { + logger.removeHandler(fileTxt); + oldFileTxt.flush(); + oldFileTxt.close(); + } + + String fileName; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss"); + + try { + fileName = Configuration.getFFDecHome() + File.separator + "logs" + File.separator; + if (Configuration.useDetailedLogging.get()) { + fileName += "log-" + sdf.format(new Date()) + ".txt"; + } else { + fileName += "log.txt"; + } + File f = new File(fileName).getParentFile(); + if (!f.exists()) { + f.mkdir(); + } + fileTxt = new FileHandler(fileName); + } catch (IOException | SecurityException ex) { + logger.log(Level.SEVERE, null, ex); + } + + Formatter formatterTxt = new LogFormatter(); + fileTxt.setFormatter(formatterTxt); + logger.addHandler(fileTxt); + + if (!GraphicsEnvironment.isHeadless() && ErrorLogFrame.hasInstance()) { + ErrorLogFrame.getInstance().clearErrorState(); + } + + sdf = new SimpleDateFormat("yyyy-MM-dd"); + logger.log(Level.INFO, "Date: {0}", sdf.format(new Date())); + logger.log(Level.INFO, ApplicationInfo.applicationVerName); + logger.log(Level.INFO, "{0} {1} {2}", new Object[]{ + System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")}); + logger.log(Level.INFO, "{0} {1} {2}", new Object[]{ + System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("os.arch")}); + } + + public static void initLogging(boolean debug) { + try { + Logger logger = Logger.getLogger(""); + logger.setLevel(Configuration.logLevel); + + Handler[] handlers = logger.getHandlers(); + for (int i = handlers.length - 1; i >= 0; i--) { + logger.removeHandler(handlers[i]); + } + + ConsoleHandler conHan = new ConsoleHandler(); + conHan.setLevel(debug ? Level.CONFIG : Level.WARNING); + SimpleFormatter formatterTxt = new SimpleFormatter(); + conHan.setFormatter(formatterTxt); + logger.addHandler(conHan); + clearLogFile(); + + } catch (Exception ex) { + throw new RuntimeException("Problems with creating the log files"); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index e274eaa7d..a8008e4d4 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2885,6 +2885,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } catch (CancellationException ex) { getABCPanel().decompiledTextArea.setText("// " + AppStrings.translate("work.canceled")); } catch (Exception ex) { + Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, "Error", ex); getABCPanel().decompiledTextArea.setText("// " + AppStrings.translate("decompilationError") + ": " + ex); } }); @@ -2892,6 +2893,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se }; worker.execute(); setSourceWorker = worker; + Main.startWork(translate("work.decompiling") + "...", worker); } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 64ff16596..b459941bd 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -741,11 +741,11 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex, null, pack.allABCs); - if (!packs.isEmpty()) { - oldSp = packs.get(0).getClassPath().toString(); - } + String oldSp = pack.getClassPath().toString(); + /*List packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex, null, pack.allABCs); + if (!packs.isEmpty()) { + + }*/ String as = decompiledTextArea.getText(); abc.replaceScriptPack(pack, as); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 4880a0d34..0d7e649ff 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -275,7 +275,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL Highlighting ch = Highlighting.searchPos(classHighlights, pos); int cindex = (int) ch.getProperties().index; ABC abc = getABC(); - type.setVal(abc.instance_info.get(cindex).getName(abc.constants).getNameWithNamespace(abc.constants, true)); + type.setVal(abc.instance_info.get(cindex).getName(abc.constants).getNameWithNamespace(abc.constants).toString()); return ch.startPos; } @@ -356,7 +356,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL traitIndex.setVal(j); classTrait.setVal(false); multinameIndex.setVal(tr.name_index); - currentType = ii.getName(a.constants).getNameWithNamespace(a.constants, true); + currentType = ii.getName(a.constants).getNameWithNamespace(a.constants).toString(); found = true; break loopi; } @@ -371,7 +371,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL traitIndex.setVal(j); classTrait.setVal(true); multinameIndex.setVal(tr.name_index); - currentType = ii.getName(a.constants).getNameWithNamespace(a.constants, true); + currentType = ii.getName(a.constants).getNameWithNamespace(a.constants).toString(); found = true; break loopi; } @@ -465,7 +465,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL for (int i = 1; i < abc.constants.constant_multiname.size(); i++) { Multiname m = abc.constants.constant_multiname.get(i); if (m != null) { - if (typeName.equals(m.getNameWithNamespace(abc.constants, true))) { + if (typeName.equals(m.getNameWithNamespace(abc.constants).toString())) { return i; } } @@ -520,7 +520,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL if (tm != null) { String name = ""; if (classIndex > -1) { - name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants, false); + name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants).toPrintableString(); } Trait currentTrait = null; @@ -571,7 +571,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL } currentMethodHighlight = null; currentTrait = null; - String name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants, false); + String name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants).toPrintableString(); currentTrait = getCurrentTrait(); isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex); if (currentTrait != null) { diff --git a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java index 109b909ca..21a398abd 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java @@ -1,179 +1,179 @@ -/* - * Copyright (C) 2010-2015 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui.abc; - -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.abc.usages.InsideClassMultinameUsage; -import com.jpexs.decompiler.flash.abc.usages.MethodMultinameUsage; -import com.jpexs.decompiler.flash.abc.usages.MultinameUsage; -import com.jpexs.decompiler.flash.abc.usages.TraitMultinameUsage; -import com.jpexs.decompiler.flash.gui.AppDialog; -import com.jpexs.decompiler.flash.gui.View; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Container; -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.List; -import javax.swing.JButton; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - -/** - * - * @author JPEXS - */ -public class UsageFrame extends AppDialog implements MouseListener { - - private final JButton gotoButton = new JButton(translate("button.goto")); - - private final JButton cancelButton = new JButton(translate("button.cancel")); - - private final JList usageList; - - private final UsageListModel usageListModel; - - private final ABCPanel abcPanel; - - public UsageFrame(ABC abc, int multinameIndex, ABCPanel abcPanel, boolean definitions) { - super(abcPanel.getMainPanel().getMainFrame().getWindow()); - this.abcPanel = abcPanel; - List usages = definitions ? abc.findMultinameDefinition(multinameIndex) : abc.findMultinameUsage(multinameIndex); - Multiname m = abc.constants.constant_multiname.get(multinameIndex); - if (m.namespace_index > 0 && abc.constants.constant_namespace.get(m.namespace_index).kind != Namespace.KIND_PRIVATE) { - for (ABCContainerTag at : abc.getAbcTags()) { - ABC a = at.getABC(); - if (a == abc) { - continue; - } - int mid = a.constants.getMultinameId(m, false); - if (mid > 0) { - usages.addAll(definitions ? a.findMultinameDefinition(mid) : a.findMultinameUsage(mid)); - } - } - } - usageListModel = new UsageListModel(); - for (MultinameUsage u : usages) { - usageListModel.addElement(u); - } - usageList = new JList<>(usageListModel); - usageList.setBackground(Color.white); - gotoButton.addActionListener(this::gotoButtonActionPerformed); - cancelButton.addActionListener(this::cancelButtonActionPerformed); - - JPanel buttonsPanel = new JPanel(); - buttonsPanel.setLayout(new FlowLayout()); - buttonsPanel.add(gotoButton); - buttonsPanel.add(cancelButton); - - usageList.addMouseListener(this); - Container cont = getContentPane(); - cont.setLayout(new BorderLayout()); - cont.add(new JScrollPane(usageList), BorderLayout.CENTER); - cont.add(buttonsPanel, BorderLayout.SOUTH); - setSize(400, 300); - setTitle((definitions ? translate("dialog.title.declaration") : translate("dialog.title")) + abc.constants.getMultiname(multinameIndex).getNameWithNamespace(abc.constants, false)); - View.centerScreen(this); - View.setWindowIcon(this); - } - - public static void gotoUsage(final ABCPanel abcPanel, final MultinameUsage usage) { - if (usage instanceof InsideClassMultinameUsage) { - final InsideClassMultinameUsage icu = (InsideClassMultinameUsage) usage; - - Runnable settrait = new Runnable() { - - @Override - public void run() { - abcPanel.decompiledTextArea.removeScriptListener(this); - abcPanel.decompiledTextArea.setClassIndex(icu.classIndex); - if (usage instanceof TraitMultinameUsage) { - TraitMultinameUsage tmu = (TraitMultinameUsage) usage; - int traitIndex; - if (tmu.parentTraitIndex > -1) { - traitIndex = tmu.parentTraitIndex; - } else { - traitIndex = tmu.traitIndex; - } - if (!tmu.isStatic) { - traitIndex += abcPanel.abc.class_info.get(tmu.classIndex).static_traits.traits.size(); - } - if (tmu instanceof MethodMultinameUsage) { - MethodMultinameUsage mmu = (MethodMultinameUsage) usage; - if (mmu.isInitializer == true) { - traitIndex = abcPanel.abc.class_info.get(mmu.classIndex).static_traits.traits.size() + abcPanel.abc.instance_info.get(mmu.classIndex).instance_traits.traits.size() + (mmu.isStatic ? 1 : 0); - } - } - abcPanel.decompiledTextArea.gotoTrait(traitIndex); - } - } - }; - - if (abcPanel.decompiledTextArea.getClassIndex() == icu.classIndex && abcPanel.abc == icu.abc) { - settrait.run(); - } else { - abcPanel.decompiledTextArea.addScriptListener(settrait); - abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.abc.instance_info.get(icu.classIndex).getName(abcPanel.abc.constants).getNameWithNamespace(abcPanel.abc.constants, false)); - } - } - } - - private void gotoUsage() { - if (usageList.getSelectedIndex() != -1) { - MultinameUsage usage = usageListModel.getUsage(usageList.getSelectedIndex()); - gotoUsage(abcPanel, usage); - } - } - - private void gotoButtonActionPerformed(ActionEvent evt) { - gotoUsage(); - setVisible(false); - } - - private void cancelButtonActionPerformed(ActionEvent evt) { - setVisible(false); - } - - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - gotoUsage(); - } - } - - @Override - public void mousePressed(MouseEvent e) { - } - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } -} +/* + * Copyright (C) 2010-2015 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.abc; + +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.abc.usages.InsideClassMultinameUsage; +import com.jpexs.decompiler.flash.abc.usages.MethodMultinameUsage; +import com.jpexs.decompiler.flash.abc.usages.MultinameUsage; +import com.jpexs.decompiler.flash.abc.usages.TraitMultinameUsage; +import com.jpexs.decompiler.flash.gui.AppDialog; +import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.List; +import javax.swing.JButton; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +/** + * + * @author JPEXS + */ +public class UsageFrame extends AppDialog implements MouseListener { + + private final JButton gotoButton = new JButton(translate("button.goto")); + + private final JButton cancelButton = new JButton(translate("button.cancel")); + + private final JList usageList; + + private final UsageListModel usageListModel; + + private final ABCPanel abcPanel; + + public UsageFrame(ABC abc, int multinameIndex, ABCPanel abcPanel, boolean definitions) { + super(abcPanel.getMainPanel().getMainFrame().getWindow()); + this.abcPanel = abcPanel; + List usages = definitions ? abc.findMultinameDefinition(multinameIndex) : abc.findMultinameUsage(multinameIndex); + Multiname m = abc.constants.constant_multiname.get(multinameIndex); + if (m.namespace_index > 0 && abc.constants.constant_namespace.get(m.namespace_index).kind != Namespace.KIND_PRIVATE) { + for (ABCContainerTag at : abc.getAbcTags()) { + ABC a = at.getABC(); + if (a == abc) { + continue; + } + int mid = a.constants.getMultinameId(m, false); + if (mid > 0) { + usages.addAll(definitions ? a.findMultinameDefinition(mid) : a.findMultinameUsage(mid)); + } + } + } + usageListModel = new UsageListModel(); + for (MultinameUsage u : usages) { + usageListModel.addElement(u); + } + usageList = new JList<>(usageListModel); + usageList.setBackground(Color.white); + gotoButton.addActionListener(this::gotoButtonActionPerformed); + cancelButton.addActionListener(this::cancelButtonActionPerformed); + + JPanel buttonsPanel = new JPanel(); + buttonsPanel.setLayout(new FlowLayout()); + buttonsPanel.add(gotoButton); + buttonsPanel.add(cancelButton); + + usageList.addMouseListener(this); + Container cont = getContentPane(); + cont.setLayout(new BorderLayout()); + cont.add(new JScrollPane(usageList), BorderLayout.CENTER); + cont.add(buttonsPanel, BorderLayout.SOUTH); + setSize(400, 300); + setTitle((definitions ? translate("dialog.title.declaration") : translate("dialog.title")) + abc.constants.getMultiname(multinameIndex).getNameWithNamespace(abc.constants).toPrintableString()); + View.centerScreen(this); + View.setWindowIcon(this); + } + + public static void gotoUsage(final ABCPanel abcPanel, final MultinameUsage usage) { + if (usage instanceof InsideClassMultinameUsage) { + final InsideClassMultinameUsage icu = (InsideClassMultinameUsage) usage; + + Runnable settrait = new Runnable() { + + @Override + public void run() { + abcPanel.decompiledTextArea.removeScriptListener(this); + abcPanel.decompiledTextArea.setClassIndex(icu.classIndex); + if (usage instanceof TraitMultinameUsage) { + TraitMultinameUsage tmu = (TraitMultinameUsage) usage; + int traitIndex; + if (tmu.parentTraitIndex > -1) { + traitIndex = tmu.parentTraitIndex; + } else { + traitIndex = tmu.traitIndex; + } + if (!tmu.isStatic) { + traitIndex += abcPanel.abc.class_info.get(tmu.classIndex).static_traits.traits.size(); + } + if (tmu instanceof MethodMultinameUsage) { + MethodMultinameUsage mmu = (MethodMultinameUsage) usage; + if (mmu.isInitializer == true) { + traitIndex = abcPanel.abc.class_info.get(mmu.classIndex).static_traits.traits.size() + abcPanel.abc.instance_info.get(mmu.classIndex).instance_traits.traits.size() + (mmu.isStatic ? 1 : 0); + } + } + abcPanel.decompiledTextArea.gotoTrait(traitIndex); + } + } + }; + + if (abcPanel.decompiledTextArea.getClassIndex() == icu.classIndex && abcPanel.abc == icu.abc) { + settrait.run(); + } else { + abcPanel.decompiledTextArea.addScriptListener(settrait); + abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.abc.instance_info.get(icu.classIndex).getName(abcPanel.abc.constants).getNameWithNamespace(abcPanel.abc.constants).toPrintableString()); + } + } + } + + private void gotoUsage() { + if (usageList.getSelectedIndex() != -1) { + MultinameUsage usage = usageListModel.getUsage(usageList.getSelectedIndex()); + gotoUsage(abcPanel, usage); + } + } + + private void gotoButtonActionPerformed(ActionEvent evt) { + gotoUsage(); + setVisible(false); + } + + private void cancelButtonActionPerformed(ActionEvent evt) { + setVisible(false); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + gotoUsage(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/debugger/DebuggerTools.java b/src/com/jpexs/decompiler/flash/gui/debugger/DebuggerTools.java index d519d6808..6a6abcf3f 100644 --- a/src/com/jpexs/decompiler/flash/gui/debugger/DebuggerTools.java +++ b/src/com/jpexs/decompiler/flash/gui/debugger/DebuggerTools.java @@ -93,7 +93,7 @@ public class DebuggerTools { ABC a = ct.getABC(); for (int i = 1; i < a.constants.constant_multiname.size(); i++) { Multiname m = a.constants.constant_multiname.get(i); - if ("trace".equals(m.getNameWithNamespace(a.constants, true))) { + if ("trace".equals(m.getNameWithNamespace(a.constants).toString())) { m.namespace_index = a.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, a.constants.getStringId(debuggerPkg, true)), 0, true); m.name_index = a.constants.getStringId(fname, true); ((Tag) ct).setModified(true); @@ -116,7 +116,7 @@ public class DebuggerTools { ABC a = ct.getABC(); for (int i = 1; i < a.constants.constant_multiname.size(); i++) { Multiname m = a.constants.constant_multiname.get(i); - String packageStr = m.getNameWithNamespace(a.constants, true); + String packageStr = m.getNameWithNamespace(a.constants).toString(); if (isDebuggerClass(packageStr, "debugTrace") || isDebuggerClass(packageStr, "debugAlert") || isDebuggerClass(packageStr, "debugSocket") From ec11afb0b17cbddd2ae743028479af808a302aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 12 Jun 2015 12:10:53 +0200 Subject: [PATCH 10/20] AVM2 Deobfuscator stub (similar to ActionDeobfuscator) --- .../flash/abc/avm2/AVM2Deobfuscator.java | 482 ++++++++++++++++++ .../abc/avm2/AVM2DeobfuscatorSimple.java | 360 +++++++++++++ .../avm2/FixItemCounterTranslateStack.java | 59 +++ .../localregs/SetLocalTypeIns.java | 3 +- .../flash/abc/types/MethodBody.java | 9 +- .../jpexs/decompiler/graph/ScopeStack.java | 6 +- .../decompiler/graph/TranslateStack.java | 11 + 7 files changed, 922 insertions(+), 8 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java new file mode 100644 index 000000000..e057fb9d4 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java @@ -0,0 +1,482 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.flash.action.deobfuscation.*; +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.AVM2LocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.action.ActionLocalData; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.ReturnActionItem; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.swf4.ActionAdd; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionLess; +import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; +import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; +import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; +import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; +import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; +import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; +import com.jpexs.decompiler.flash.action.swf5.ActionLess2; +import com.jpexs.decompiler.flash.action.swf5.ActionModulo; +import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; +import com.jpexs.decompiler.flash.action.swf5.ActionReturn; +import com.jpexs.decompiler.flash.action.swf6.ActionGreater; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import java.io.IOException; +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * AVM2 Deobfuscator - FIXME!!! Not ready yet! + * + * @author JPEXS + */ +public class AVM2Deobfuscator extends AVM2DeobfuscatorSimple { + + private final int executionLimit = 30000; + + @Override + public void actionListParsed(ActionList actions, SWF swf) { + + } + + @Override + public void deobfuscate(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + removeZeroJumps(body.getCode(), body); + } + + private boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) { + AVM2Code code = body.getCode(); + if (code.code.size() == 0) { + return false; + } + System.err.println("============================================="); + for (int i = 0; i < code.code.size(); i++) { + ExecutionResult result = new ExecutionResult(); + System.err.println("Execute from " + i); + executeActions(classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result); + + if (result.idx != -1) { + int newIstructionCount = 1; // jump + if (!result.stack.isEmpty()) { + newIstructionCount++; + } + newIstructionCount += 2 * result.variables.size(); + + if (newIstructionCount * 2 < result.instructionsProcessed) { + AVM2Instruction target = code.code.get(result.idx); + AVM2Instruction prevAction = code.code.get(i); + + for (int variableName : result.variables.keySet()) { + Object value = result.variables.get(variableName); + /*ActionPush push = new ActionPush(variableName); + push.values.add(value);*/ + AVM2Instruction push = makePush(value, cpool); + + code.insertInstruction(i++, push); + push.offset = prevAction.offset; + + code.insertInstruction(i++, push); + prevAction = push; + + /*if (result.defines.contains(variableName)) { + //ActionDefineLocal defineLocal = new ActionDefineLocal(); + AVM2Instruction defineLocal = new AVM2Instruction(prevAction.offset, new SetLocalIns(), new int[]{}); + defineLocal.setAddress(prevAction.getAddress()); + code.addAction(i++, defineLocal); + prevAction = defineLocal; + } else { + ActionSetVariable setVariable = new ActionSetVariable(); + setVariable.setAddress(prevAction.getAddress()); + code.addAction(i++, setVariable); + prevAction = setVariable; + }*/ + AVM2Instruction setVariable = new AVM2Instruction(prevAction.offset, new SetLocalIns(), new int[]{}); + code.insertInstruction(i++, setVariable); + prevAction = setVariable; + } + + if (!result.stack.isEmpty()) { + //ActionPush push = new ActionPush(0); + //push.values.clear(); + long ofs = prevAction.offset; + for (GraphTargetItem graphTargetItem : result.stack) { + //DirectValueActionItem dv = (DirectValueActionItem) graphTargetItem; + //push.values.add(dv.value); + AVM2Instruction push = makePush(cpool, graphTargetItem); + push.offset = ofs; + code.insertInstruction(i++, push); + ofs += push.getBytes().length; + prevAction = push; + } + } + + //ctionJump jump = new ActionJump(0); + AVM2Instruction jump = new AVM2Instruction(prevAction.offset, new JumpIns(), new int[]{0}); + //jump.setAddress(prevAction.getAddress()); + jump.operands[0] = (int) (target.offset - jump.offset - jump.getBytes().length); + code.insertInstruction(i++, jump); + return true; + } + } + } + + return false; + } + + private AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool cpool, MethodBody body, boolean isStatic, int classIndex) { + AVM2LocalData localData = new AVM2LocalData(); + localData.isStatic = isStatic; + localData.classIndex = classIndex; + localData.localRegs = new HashMap<>(); + localData.scopeStack = new ScopeStack(); + localData.constants = cpool; + localData.methodInfo = abc.method_info; + localData.methodBody = body; + localData.abc = abc; + localData.localRegNames = new HashMap<>(); + localData.fullyQualifiedNames = new ArrayList<>(); + localData.parsedExceptions = new ArrayList<>(); + localData.finallyJumps = new HashMap<>(); + localData.ignoredSwitches = new HashMap<>(); + localData.ignoredSwitches2 = new ArrayList<>(); + localData.scriptIndex = scriptIndex; + localData.localRegAssignmentIps = new HashMap<>(); + localData.ip = 0; + localData.refs = new HashMap<>(); + localData.code = body.getCode(); + return localData; + } + + private void executeActions(int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result) { + List output = new ArrayList<>(); + AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex); + localData.localRegs.put(0, new NullAVM2Item(null));//this + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); + int instructionsProcessed = 0; + + try { + while (true) { + if (idx > endIdx) { + break; + } + + AVM2Instruction action = code.code.get(idx); + instructionsProcessed++; + + if (instructionsProcessed > executionLimit) { + break; + } + + /*if (action instanceof ActionDefineLocal) { + GraphTargetItem top = stack.pop(); + String variableName = stack.peek().getResult().toString(); + result.defines.add(variableName); + stack.push(top); + }*/ + if (action.definition instanceof GetLocalTypeIns) { + int regId = ((GetLocalTypeIns) action.definition).getRegisterId(action);//stack.peek().getResult().toString(); + if (!localData.localRegs.containsKey(regId)) { + break; + } + } + + /*if (action instanceof ActionCallFunction) { + String functionName = stack.pop().getResult().toString(); + long numArgs = EcmaScript.toUint32(stack.pop().getResult()); + if (numArgs == 0) { + if (fakeFunctions != null && fakeFunctions.containsKey(functionName)) { + stack.push(new DirectValueActionItem(fakeFunctions.get(functionName))); + } else { + break; + } + } else { + break; + } + } else { + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + }*/ + System.err.println("Translating " + action); + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + Class allowedDefs[] = new Class[]{ + PushByteIns.class, + PushShortIns.class, + PushIntIns.class, + PushDoubleIns.class, + PushStringIns.class, + PushNullIns.class, + PushUndefinedIns.class, + PushFalseIns.class, + PushTrueIns.class, + DupIns.class, + SwapIns.class, + AddIns.class, + AddIIns.class, + SubtractIns.class, + SubtractIIns.class, + ModuloIns.class, + MultiplyIns.class, + BitAndIns.class, + BitXorIns.class, + BitOrIns.class, + LShiftIns.class, + RShiftIns.class, + URShiftIns.class, + EqualsIns.class, + NotIns.class, + IfTypeIns.class, + JumpIns.class, + IncrementIns.class, + IncrementIIns.class, + DecrementIns.class, + DecrementIIns.class, + SetLocalTypeIns.class, + GetLocalTypeIns.class, + GreaterEqualsIns.class, + GreaterThanIns.class, + LessThanIns.class, + LessEqualsIns.class, + StrictEqualsIns.class, + IfTypeIns.class, + ReturnVoidIns.class, + ReturnValueIns.class, + NewFunctionIns.class, + PopIns.class, + PushScopeIns.class + }; + + InstructionDefinition def = action.definition; + + boolean ok = false; + for (Class s : allowedDefs) { + if (s.isAssignableFrom(def.getClass())) { + ok = true; + break; + } + } + if (!ok) { + System.err.println("Broken"); + break; + } + + + /*for (String variable : localData.variables.keySet()) { + System.out.println(Helper.byteArrToString(variable.getBytes())); + }*/ + idx++; + + if (action.definition instanceof JumpIns) { + + long address = action.offset + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); + if (idx == -1) { + throw new TranslateException("Jump target not found: " + address); + } + } + + if (action.definition instanceof IfTypeIns) { + if (EcmaScript.toBoolean(stack.pop().getResult())) { + long address = action.offset + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address); + if (idx == -1) { + throw new TranslateException("If target not found: " + address); + } + } + } + + if (/*localData.variables.size() == 1 && */stack.allItemsFixed()) { + result.idx = idx == code.code.size() ? idx - 1 : idx; + result.instructionsProcessed = instructionsProcessed; + result.variables.clear(); + for (int variableName : localData.localRegs.keySet()) { + Object value = localData.localRegs.get(variableName).getResult(); + result.variables.put(variableName, value); + } + result.stack.clear(); + result.stack.addAll(stack); + } + + if (action.definition instanceof ReturnValueIns) { + if (output.size() > 0) { + ReturnValueAVM2Item ret = (ReturnValueAVM2Item) output.get(output.size() - 1); + result.resultValue = ret.value.getResult(); + } + break; + } + + if (action.definition instanceof ReturnVoidIns) { + break; + } + } + } catch (EmptyStackException | TranslateException | InterruptedException ex) { + //ex.printStackTrace(); + } + } + + /*private Map getFakeFunctionResults(ActionList actions) { + + Map results = new HashMap<>(); + + for (int i = 0; i < actions.size(); i++) { + Action action = actions.get(i); + if (action instanceof ActionDefineFunction) { + ActionDefineFunction def = (ActionDefineFunction) action; + if (def.paramNames.isEmpty()) { + ExecutionResult result = new ExecutionResult(); + List lastActions = actions.getContainerLastActions(action); + int lastActionIdx = actions.indexOf(lastActions.get(0)); + executeActions(actions, i + 1, lastActionIdx, null, result, null); + if (result.resultValue != null) { + results.put(def.functionName, result.resultValue); + for (int j = i; j <= lastActionIdx; j++) { + actions.removeAction(i); + } + } + } + } + } + + return results; + } + + @Override + public byte[] proxyFileCatched(byte[] data) { + return null; + } + + @Override + public void swfParsed(SWF swf) { + } + + @Override + public void abcParsed(ABC abc, SWF swf) { + } + + @Override + public void methodBodyParsed(MethodBody body, SWF swf) { + }*/ + class ExecutionResult { + + public int idx = -1; + + public int instructionsProcessed = -1; + + //public ActionConstantPool constantPool; + public Map variables = new HashMap<>(); + + //public Set defines = new HashSet<>(); + public TranslateStack stack = new TranslateStack("?"); + + public ScopeStack scopeStack = new ScopeStack(); + + public Object resultValue; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java new file mode 100644 index 000000000..1e21be20b --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.AVM2LocalData; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; +import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.FalseItem; +import com.jpexs.decompiler.graph.model.TrueItem; +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { + + private final int executionLimit = 30000; + + @Override + public void actionListParsed(ActionList actions, SWF swf) { + + } + + protected AVM2Instruction makePush(Object ovalue, AVM2ConstantPool cpool) { + if (ovalue instanceof Long) { + long value = (Long) ovalue; + if (value >= -128 && value <= 127) { + return new AVM2Instruction(0, new PushByteIns(), new int[]{(int) (long) value}); + } else if (value >= -32768 && value <= 32767) { + return new AVM2Instruction(0, new PushShortIns(), new int[]{((int) (long) value) & 0xffff}); + } else { + return new AVM2Instruction(0, new PushIntIns(), new int[]{cpool.getIntId(value, true)}); + } + } + if (ovalue instanceof Double) { + return new AVM2Instruction(0, new PushDoubleIns(), new int[]{cpool.getDoubleId((Double) ovalue, true)}); + } + if (ovalue instanceof String) { + return new AVM2Instruction(0, new PushStringIns(), new int[]{cpool.getStringId((String) ovalue, true)}); + } + if (ovalue instanceof Boolean) { + if ((Boolean) ovalue) { + return new AVM2Instruction(0, new PushTrueIns(), new int[]{}); + } + return new AVM2Instruction(0, new PushFalseIns(), new int[]{}); + } + if (ovalue instanceof Null) { + return new AVM2Instruction(0, new PushNullIns(), new int[]{}); + } + if (ovalue instanceof Undefined) { + return new AVM2Instruction(0, new PushUndefinedIns(), new int[]{}); + } + return null; + } + + protected AVM2Instruction makePush(AVM2ConstantPool cpool, GraphTargetItem graphTargetItem) { + AVM2Instruction ins = null; + if (graphTargetItem instanceof IntegerValueAVM2Item) { + IntegerValueAVM2Item iv = (IntegerValueAVM2Item) graphTargetItem; + return makePush(iv.value, cpool); + } else if (graphTargetItem instanceof FloatValueAVM2Item) { + FloatValueAVM2Item fv = (FloatValueAVM2Item) graphTargetItem; + return makePush(fv.value, cpool); + } else if (graphTargetItem instanceof StringAVM2Item) { + StringAVM2Item fv = (StringAVM2Item) graphTargetItem; + return makePush(fv.value, cpool); + } else if (graphTargetItem instanceof TrueItem) { + return makePush(Boolean.TRUE, cpool); + } else if (graphTargetItem instanceof FalseItem) { + return makePush(Boolean.FALSE, cpool); + } else if (graphTargetItem instanceof NullAVM2Item) { + return makePush(new Null(), cpool); + } else if (graphTargetItem instanceof UndefinedAVM2Item) { + return makePush(new Undefined(), cpool); + } else { + return null; + } + } + + private boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + AVM2Code code = body.getCode(); + if (code.code.size() == 0) { + return false; + } + System.err.println("====================================================="); + + for (int i = 0; i < code.code.size(); i++) { + ExecutionResult result = new ExecutionResult(); + System.err.println("Execute from " + i); + executeActions(code, i, code.code.size() - 1, result); + + if (result.idx != -1) { + int newIstructionCount = 1; // jump + if (!result.stack.isEmpty()) { + newIstructionCount += result.stack.size(); + } + + if (newIstructionCount < result.instructionsProcessed) { + AVM2Instruction target = code.code.get(result.idx); + AVM2Instruction prevAction = code.code.get(i); + + if (result.stack.isEmpty() && prevAction.definition instanceof JumpIns) { + prevAction.operands[0] = ((int) (target.getOffset() - prevAction.getOffset() - prevAction.getBytes().length)); + } else { + if (!result.stack.isEmpty()) { + for (GraphTargetItem graphTargetItem : result.stack) { + AVM2Instruction ins = makePush(cpool, graphTargetItem); + if (ins != null) { + code.insertInstruction(i++, ins); + } + prevAction = ins; + //DirectValueActionItem dv = (DirectValueActionItem) graphTargetItem; + //push.values.add(dv.value); + } + //push.setAddress(prevAction.getAddress()); + + } + + AVM2Instruction jump = new AVM2Instruction(0, new JumpIns(), new int[]{0}); + jump.offset = prevAction.offset; + jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length)); + code.insertInstruction(i++, jump); + } + + AVM2Instruction nextAction = code.code.size() > i ? code.code.get(i) : null; + + removeUnreachableActions(code, cpool, trait, minfo, body); + removeZeroJumps(code, body); + + if (nextAction != null) { + int nextIdx = code.code.indexOf(nextAction); + if (nextIdx < i) { + i = nextIdx; + } + } + } + } + } + + return false; + } + + protected void removeUnreachableActions(AVM2Code code, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + code.removeDeadCode(cpool, trait, minfo, body); + } + + protected boolean removeZeroJumps(AVM2Code actions, MethodBody body) { + boolean result = false; + for (int i = 0; i < actions.code.size(); i++) { + AVM2Instruction action = actions.code.get(i); + if (action.definition instanceof JumpIns && action.operands[0] == 0) { + actions.removeInstruction(i, body); + i--; + result = true; + } + } + return result; + } + + private void executeActions(AVM2Code code, int idx, int endIdx, ExecutionResult result) { + List output = new ArrayList<>(); + AVM2LocalData localData = new AVM2LocalData(); + + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); + int instructionsProcessed = 0; + + try { + while (true) { + if (idx > endIdx) { + break; + } + + if (instructionsProcessed > executionLimit) { + break; + } + + AVM2Instruction action = code.code.get(idx); + + /*System.out.print(action.getASMSource(actions, new ArrayList(), ScriptExportMode.PCODE)); + for (int j = 0; j < stack.size(); j++) { + System.out.print(" '" + stack.get(j).getResult() + "'"); + } + System.out.println();*/ + InstructionDefinition def = action.definition; + + Class allowedDefs[] = new Class[]{ + PushByteIns.class, + PushShortIns.class, + PushIntIns.class, + PushDoubleIns.class, + PushStringIns.class, + PushNullIns.class, + PushUndefinedIns.class, + PushFalseIns.class, + PushTrueIns.class, + DupIns.class, + SwapIns.class, + AddIns.class, + AddIIns.class, + SubtractIns.class, + SubtractIIns.class, + ModuloIns.class, + MultiplyIns.class, + BitAndIns.class, + BitXorIns.class, + BitOrIns.class, + LShiftIns.class, + RShiftIns.class, + URShiftIns.class, + EqualsIns.class, + NotIns.class, + IfTypeIns.class, + JumpIns.class + }; + + boolean ok = false; + for (Class s : allowedDefs) { + if (s.isAssignableFrom(def.getClass())) { + ok = true; + break; + } + } + if (!ok) { + break; + } + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + + idx++; + + if (def instanceof JumpIns) { + //ActionJump jump = (ActionJump) action; + long address = action.getOffset() + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address); + if (idx == -1) { + throw new TranslateException("Jump target not found: " + address); + } + } + + if (def instanceof IfTypeIns) { + //ActionIf aif = (ActionIf) action; + if (EcmaScript.toBoolean(stack.pop().getResult())) { + long address = action.offset + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); + if (idx == -1) { + throw new TranslateException("If target not found: " + address); + } + } + } + + instructionsProcessed++; + + if (stack.allItemsFixed()) { + result.idx = idx == code.code.size() ? idx - 1 : idx; + result.instructionsProcessed = instructionsProcessed; + result.stack.clear(); + result.stack.addAll(stack); + } + } + } catch (EmptyStackException | TranslateException | InterruptedException ex) { + } + } + + @Override + public byte[] proxyFileCatched(byte[] data) { + return null; + } + + @Override + public void swfParsed(SWF swf) { + } + + @Override + public void abcParsed(ABC abc, SWF swf) { + } + + @Override + public void methodBodyParsed(MethodBody body, SWF swf) { + + } + + public void deobfuscate(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + removeZeroJumps(body.getCode(), body); + } + + class ExecutionResult { + + public int idx = -1; + + public int instructionsProcessed = -1; + + public TranslateStack stack = new TranslateStack("?"); + + public Object resultValue; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java new file mode 100644 index 000000000..05f02f399 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateStack; + +/** + * + * @author JPEXS + */ +public class FixItemCounterTranslateStack extends TranslateStack { + + private int fixItemCount = Integer.MAX_VALUE; + + public FixItemCounterTranslateStack(String path) { + super(null); //null path => do not add PushItems + } + + @Override + public GraphTargetItem pop() { + GraphTargetItem result = super.pop(); + int itemCount = size(); + if (itemCount < fixItemCount) { + fixItemCount = itemCount; + } + return result; + } + + @Override + public synchronized GraphTargetItem remove(int index) { + if (index < fixItemCount) { + fixItemCount = index; + } + return super.remove(index); + } + + public boolean allItemsFixed() { + return size() <= fixItemCount; + } + + public int getFixItemCount() { + return fixItemCount; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java index 85895b8e5..57158d6a3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java @@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.NotCompileTimeItem; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateStack; import java.util.HashMap; @@ -116,7 +117,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S } //if(val.startsWith("catchscope ")) return; - //if(val.startsWith("newactivation()")) return; + //if(val.startsWith("newactivation()")) return; output.add(new SetLocalAVM2Item(ins, regId, value)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 47817f2b5..303150337 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ABCInputStream; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscator; import com.jpexs.decompiler.flash.abc.avm2.CodeStats; import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -279,13 +280,9 @@ public final class MethodBody implements Cloneable { deobfuscated.markMappedOffsets(); //deobfuscated.inlineJumpExit(); if (Configuration.autoDeobfuscate.get()) { - try { - deobfuscated.removeTraps(constants, trait, method_info.get(this.method_info), b, abc, scriptIndex, classIndex, isStatic, path); - } catch (StackOverflowError ex) { - logger.log(Level.SEVERE, "Error during remove traps in " + path, ex); - } + AVM2Deobfuscator deo = new AVM2Deobfuscator(); + deo.deobfuscate(classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b); } - //deobfuscated.restoreControlFlow(constants, b); return b; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java index af1152907..bb5478932 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java @@ -22,5 +22,9 @@ import java.util.Stack; * * @author JPEXS */ -public class ScopeStack extends Stack { +public class ScopeStack extends TranslateStack { + + public ScopeStack() { + super("scope"); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java index cc68f15ea..72ca11740 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java @@ -39,6 +39,17 @@ public class TranslateStack extends Stack { return path; } + @Override + public synchronized GraphTargetItem get(int index) { + if (path != null) { + if (index >= this.size() || index < 0) { + Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attemp to Get item outside of bounds of stack", path); + return pop; + } + } + return super.get(index); + } + @Override public synchronized GraphTargetItem peek() { if (path != null) { From fbd1c1644c363aadc5a1055ae7b5272aee895e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 12 Jun 2015 12:51:52 +0200 Subject: [PATCH 11/20] unused imports --- .../flash/abc/avm2/AVM2Deobfuscator.java | 47 ------------------- 1 file changed, 47 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java index e057fb9d4..c82ee8952 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java @@ -16,10 +16,7 @@ */ package com.jpexs.decompiler.flash.abc.avm2; -import com.jpexs.decompiler.flash.action.deobfuscation.*; -import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; @@ -70,65 +67,21 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.action.ActionListReader; -import com.jpexs.decompiler.flash.action.ActionLocalData; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.ReturnActionItem; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.swf4.ActionAdd; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionLess; -import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; -import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; -import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; -import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; -import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; -import com.jpexs.decompiler.flash.action.swf5.ActionLess2; -import com.jpexs.decompiler.flash.action.swf5.ActionModulo; -import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; -import com.jpexs.decompiler.flash.action.swf5.ActionReturn; -import com.jpexs.decompiler.flash.action.swf6.ActionGreater; import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.flash.ecma.Undefined; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateException; import com.jpexs.decompiler.graph.TranslateStack; -import java.io.IOException; import java.util.ArrayList; import java.util.EmptyStackException; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; /** * From 84398eaccf02707e46f67a26b1e60f8377788a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 20 Jun 2015 20:27:39 +0200 Subject: [PATCH 12/20] New AS3 Deobfuscation method similar to that for AS1/2 --- .../decompiler/flash/abc/avm2/AVM2Code.java | 53 +- .../flash/abc/avm2/AVM2Deobfuscator.java | 435 ------ .../abc/avm2/AVM2DeobfuscatorRegisters.java | 250 ++++ .../abc/avm2/AVM2DeobfuscatorSimple.java | 131 +- .../localregs/SetLocalTypeIns.java | 5 +- .../abc/avm2/model/LocalRegAVM2Item.java | 2 +- .../avm2/parser/script/ActionScriptLexer.java | 2 +- .../flash/abc/types/MethodBody.java | 22 +- .../jpexs/decompiler/graph/ScopeStack.java | 8 +- .../decompiler/graph/model/FalseItem.java | 10 + .../decompiler/graph/model/TrueItem.java | 11 + .../flash/ActionScript3DeobfuscatorTest.java | 262 ++++ .../flash/gui/locales/MainFrame.properties | 2 +- .../flash/gui/locales/MainFrame_ca.properties | 2 +- .../flash/gui/locales/MainFrame_cs.properties | 2 +- .../flash/gui/locales/MainFrame_es.properties | 2 +- .../flash/gui/locales/MainFrame_fr.properties | 2 +- .../flash/gui/locales/MainFrame_hu.properties | 2 +- .../flash/gui/locales/MainFrame_pl.properties | 2 +- .../flash/gui/locales/MainFrame_ru.properties | 1156 ++++++++-------- .../flash/gui/locales/MainFrame_sv.properties | 1232 ++++++++--------- .../flash/gui/locales/MainFrame_zh.properties | 2 +- 22 files changed, 1890 insertions(+), 1705 deletions(-) delete mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorRegisters.java create mode 100644 libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 0e3c62f4c..6b1bacd0b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1150,7 +1150,7 @@ public class AVM2Code implements Cloneable { } int ret = posCache.indexOf(address); if (ret == -1) { - throw new ConvertException("Bad jump try conver ofs" + Helper.formatAddress(address) + " ", -1); + throw new ConvertException("Invalid jump to ofs" + Helper.formatAddress(address), -1); } return ret; } @@ -1843,7 +1843,20 @@ public class AVM2Code implements Cloneable { invalidateCache(); } + /** + * @param pos + * @param instruction + */ public void insertInstruction(int pos, AVM2Instruction instruction) { + insertInstruction(pos, instruction, true, false); + } + + public void replaceInstruction(int idx, AVM2Instruction ins, MethodBody body) { + insertInstruction(idx, ins, true, true); + removeInstruction(idx + 1, body); + } + + public void insertInstruction(int pos, AVM2Instruction instruction, boolean preRefsToThis, boolean postRefsToThis) { if (pos < 0) { pos = 0; } @@ -1857,31 +1870,43 @@ public class AVM2Code implements Cloneable { instruction.offset = code.get(pos).offset; } - for (int i = 0; i < pos; i++) { - for (int j = 0; j < code.get(i).definition.operands.length; j++) { - if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; - if (target >= instruction.offset) { - code.get(i).operands[j] += byteCount; + { + for (int i = 0; i < pos; i++) { + for (int j = 0; j < code.get(i).definition.operands.length; j++) { + if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { + long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; + if (target > instruction.offset) { + code.get(i).operands[j] += byteCount; + } + if (target == instruction.offset && !preRefsToThis) { + code.get(i).operands[j] += byteCount; + } + } } } } - for (int i = pos; i < code.size(); i++) { - for (int j = 0; j < code.get(i).definition.operands.length; j++) { - if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; - if (target < instruction.offset) { - code.get(i).operands[j] -= byteCount; + { + for (int i = pos; i < code.size(); i++) { + for (int j = 0; j < code.get(i).definition.operands.length; j++) { + if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { + long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; + if (target < instruction.offset) { + code.get(i).operands[j] -= byteCount; + } + if (target == instruction.offset && postRefsToThis) { + code.get(i).operands[j] -= byteCount; + } } } } } - for (int i = pos + 1; i < code.size(); i++) { + for (int i = pos; i < code.size(); i++) { code.get(i).offset += byteCount; } code.add(pos, instruction); + invalidateCache(); } @SuppressWarnings("unchecked") diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java deleted file mode 100644 index c82ee8952..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscator.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2010-2015 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.AVM2LocalData; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; -import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.ArrayList; -import java.util.EmptyStackException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * - * AVM2 Deobfuscator - FIXME!!! Not ready yet! - * - * @author JPEXS - */ -public class AVM2Deobfuscator extends AVM2DeobfuscatorSimple { - - private final int executionLimit = 30000; - - @Override - public void actionListParsed(ActionList actions, SWF swf) { - - } - - @Override - public void deobfuscate(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { - removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); - removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); - removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); - removeZeroJumps(body.getCode(), body); - } - - private boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) { - AVM2Code code = body.getCode(); - if (code.code.size() == 0) { - return false; - } - System.err.println("============================================="); - for (int i = 0; i < code.code.size(); i++) { - ExecutionResult result = new ExecutionResult(); - System.err.println("Execute from " + i); - executeActions(classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result); - - if (result.idx != -1) { - int newIstructionCount = 1; // jump - if (!result.stack.isEmpty()) { - newIstructionCount++; - } - newIstructionCount += 2 * result.variables.size(); - - if (newIstructionCount * 2 < result.instructionsProcessed) { - AVM2Instruction target = code.code.get(result.idx); - AVM2Instruction prevAction = code.code.get(i); - - for (int variableName : result.variables.keySet()) { - Object value = result.variables.get(variableName); - /*ActionPush push = new ActionPush(variableName); - push.values.add(value);*/ - AVM2Instruction push = makePush(value, cpool); - - code.insertInstruction(i++, push); - push.offset = prevAction.offset; - - code.insertInstruction(i++, push); - prevAction = push; - - /*if (result.defines.contains(variableName)) { - //ActionDefineLocal defineLocal = new ActionDefineLocal(); - AVM2Instruction defineLocal = new AVM2Instruction(prevAction.offset, new SetLocalIns(), new int[]{}); - defineLocal.setAddress(prevAction.getAddress()); - code.addAction(i++, defineLocal); - prevAction = defineLocal; - } else { - ActionSetVariable setVariable = new ActionSetVariable(); - setVariable.setAddress(prevAction.getAddress()); - code.addAction(i++, setVariable); - prevAction = setVariable; - }*/ - AVM2Instruction setVariable = new AVM2Instruction(prevAction.offset, new SetLocalIns(), new int[]{}); - code.insertInstruction(i++, setVariable); - prevAction = setVariable; - } - - if (!result.stack.isEmpty()) { - //ActionPush push = new ActionPush(0); - //push.values.clear(); - long ofs = prevAction.offset; - for (GraphTargetItem graphTargetItem : result.stack) { - //DirectValueActionItem dv = (DirectValueActionItem) graphTargetItem; - //push.values.add(dv.value); - AVM2Instruction push = makePush(cpool, graphTargetItem); - push.offset = ofs; - code.insertInstruction(i++, push); - ofs += push.getBytes().length; - prevAction = push; - } - } - - //ctionJump jump = new ActionJump(0); - AVM2Instruction jump = new AVM2Instruction(prevAction.offset, new JumpIns(), new int[]{0}); - //jump.setAddress(prevAction.getAddress()); - jump.operands[0] = (int) (target.offset - jump.offset - jump.getBytes().length); - code.insertInstruction(i++, jump); - return true; - } - } - } - - return false; - } - - private AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool cpool, MethodBody body, boolean isStatic, int classIndex) { - AVM2LocalData localData = new AVM2LocalData(); - localData.isStatic = isStatic; - localData.classIndex = classIndex; - localData.localRegs = new HashMap<>(); - localData.scopeStack = new ScopeStack(); - localData.constants = cpool; - localData.methodInfo = abc.method_info; - localData.methodBody = body; - localData.abc = abc; - localData.localRegNames = new HashMap<>(); - localData.fullyQualifiedNames = new ArrayList<>(); - localData.parsedExceptions = new ArrayList<>(); - localData.finallyJumps = new HashMap<>(); - localData.ignoredSwitches = new HashMap<>(); - localData.ignoredSwitches2 = new ArrayList<>(); - localData.scriptIndex = scriptIndex; - localData.localRegAssignmentIps = new HashMap<>(); - localData.ip = 0; - localData.refs = new HashMap<>(); - localData.code = body.getCode(); - return localData; - } - - private void executeActions(int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result) { - List output = new ArrayList<>(); - AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex); - localData.localRegs.put(0, new NullAVM2Item(null));//this - FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); - int instructionsProcessed = 0; - - try { - while (true) { - if (idx > endIdx) { - break; - } - - AVM2Instruction action = code.code.get(idx); - instructionsProcessed++; - - if (instructionsProcessed > executionLimit) { - break; - } - - /*if (action instanceof ActionDefineLocal) { - GraphTargetItem top = stack.pop(); - String variableName = stack.peek().getResult().toString(); - result.defines.add(variableName); - stack.push(top); - }*/ - if (action.definition instanceof GetLocalTypeIns) { - int regId = ((GetLocalTypeIns) action.definition).getRegisterId(action);//stack.peek().getResult().toString(); - if (!localData.localRegs.containsKey(regId)) { - break; - } - } - - /*if (action instanceof ActionCallFunction) { - String functionName = stack.pop().getResult().toString(); - long numArgs = EcmaScript.toUint32(stack.pop().getResult()); - if (numArgs == 0) { - if (fakeFunctions != null && fakeFunctions.containsKey(functionName)) { - stack.push(new DirectValueActionItem(fakeFunctions.get(functionName))); - } else { - break; - } - } else { - break; - } - } else { - action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); - }*/ - System.err.println("Translating " + action); - action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); - Class allowedDefs[] = new Class[]{ - PushByteIns.class, - PushShortIns.class, - PushIntIns.class, - PushDoubleIns.class, - PushStringIns.class, - PushNullIns.class, - PushUndefinedIns.class, - PushFalseIns.class, - PushTrueIns.class, - DupIns.class, - SwapIns.class, - AddIns.class, - AddIIns.class, - SubtractIns.class, - SubtractIIns.class, - ModuloIns.class, - MultiplyIns.class, - BitAndIns.class, - BitXorIns.class, - BitOrIns.class, - LShiftIns.class, - RShiftIns.class, - URShiftIns.class, - EqualsIns.class, - NotIns.class, - IfTypeIns.class, - JumpIns.class, - IncrementIns.class, - IncrementIIns.class, - DecrementIns.class, - DecrementIIns.class, - SetLocalTypeIns.class, - GetLocalTypeIns.class, - GreaterEqualsIns.class, - GreaterThanIns.class, - LessThanIns.class, - LessEqualsIns.class, - StrictEqualsIns.class, - IfTypeIns.class, - ReturnVoidIns.class, - ReturnValueIns.class, - NewFunctionIns.class, - PopIns.class, - PushScopeIns.class - }; - - InstructionDefinition def = action.definition; - - boolean ok = false; - for (Class s : allowedDefs) { - if (s.isAssignableFrom(def.getClass())) { - ok = true; - break; - } - } - if (!ok) { - System.err.println("Broken"); - break; - } - - - /*for (String variable : localData.variables.keySet()) { - System.out.println(Helper.byteArrToString(variable.getBytes())); - }*/ - idx++; - - if (action.definition instanceof JumpIns) { - - long address = action.offset + action.getBytes().length + action.operands[0]; - idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); - if (idx == -1) { - throw new TranslateException("Jump target not found: " + address); - } - } - - if (action.definition instanceof IfTypeIns) { - if (EcmaScript.toBoolean(stack.pop().getResult())) { - long address = action.offset + action.getBytes().length + action.operands[0]; - idx = code.adr2pos(address); - if (idx == -1) { - throw new TranslateException("If target not found: " + address); - } - } - } - - if (/*localData.variables.size() == 1 && */stack.allItemsFixed()) { - result.idx = idx == code.code.size() ? idx - 1 : idx; - result.instructionsProcessed = instructionsProcessed; - result.variables.clear(); - for (int variableName : localData.localRegs.keySet()) { - Object value = localData.localRegs.get(variableName).getResult(); - result.variables.put(variableName, value); - } - result.stack.clear(); - result.stack.addAll(stack); - } - - if (action.definition instanceof ReturnValueIns) { - if (output.size() > 0) { - ReturnValueAVM2Item ret = (ReturnValueAVM2Item) output.get(output.size() - 1); - result.resultValue = ret.value.getResult(); - } - break; - } - - if (action.definition instanceof ReturnVoidIns) { - break; - } - } - } catch (EmptyStackException | TranslateException | InterruptedException ex) { - //ex.printStackTrace(); - } - } - - /*private Map getFakeFunctionResults(ActionList actions) { - - Map results = new HashMap<>(); - - for (int i = 0; i < actions.size(); i++) { - Action action = actions.get(i); - if (action instanceof ActionDefineFunction) { - ActionDefineFunction def = (ActionDefineFunction) action; - if (def.paramNames.isEmpty()) { - ExecutionResult result = new ExecutionResult(); - List lastActions = actions.getContainerLastActions(action); - int lastActionIdx = actions.indexOf(lastActions.get(0)); - executeActions(actions, i + 1, lastActionIdx, null, result, null); - if (result.resultValue != null) { - results.put(def.functionName, result.resultValue); - for (int j = i; j <= lastActionIdx; j++) { - actions.removeAction(i); - } - } - } - } - } - - return results; - } - - @Override - public byte[] proxyFileCatched(byte[] data) { - return null; - } - - @Override - public void swfParsed(SWF swf) { - } - - @Override - public void abcParsed(ABC abc, SWF swf) { - } - - @Override - public void methodBodyParsed(MethodBody body, SWF swf) { - }*/ - class ExecutionResult { - - public int idx = -1; - - public int instructionsProcessed = -1; - - //public ActionConstantPool constantPool; - public Map variables = new HashMap<>(); - - //public Set defines = new HashSet<>(); - public TranslateStack stack = new TranslateStack("?"); - - public ScopeStack scopeStack = new ScopeStack(); - - public Object resultValue; - } -} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorRegisters.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorRegisters.java new file mode 100644 index 000000000..bf6005041 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorRegisters.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.flash.BaseLocalData; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.AVM2LocalData; +import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2GraphSource; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphPart; +import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * + * AVM2 Deobfuscator removing single assigned local registers. + * + * Example: var a = true; var b = false; ... if(a){ ...ok }else{ not executed } + * + * @author JPEXS + */ +public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { + + //private final int executionLimit = 30000; + @Override + public void actionListParsed(ActionList actions, SWF swf) { + + } + + @Override + public void deobfuscate(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + + body.getCode().markMappedOffsets(); + + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + Map singleRegisters = getSingleUseRegisters(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + replaceSingleUseRegisters(singleRegisters, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + super.deobfuscate(path, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + } + + private void replaceSingleUseRegisters(Map singleRegisters, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) { + AVM2Code code = body.getCode(); + + for (int i = 0; i < code.code.size(); i++) { + AVM2Instruction ins = code.code.get(i); + if (ins.definition instanceof SetLocalTypeIns) { + SetLocalTypeIns slt = (SetLocalTypeIns) ins.definition; + int regId = slt.getRegisterId(ins); + if (singleRegisters.containsKey(regId)) { + code.replaceInstruction(i, new AVM2Instruction(ins.offset, new DeobfuscatePopIns(), new int[]{}), body); + } + } + if (ins.definition instanceof GetLocalTypeIns) { + GetLocalTypeIns glt = (GetLocalTypeIns) ins.definition; + int regId = glt.getRegisterId(ins); + if (singleRegisters.containsKey(regId)) { + code.replaceInstruction(i, makePush(singleRegisters.get(regId).getResult(), cpool), body); + } + } + } + } + + private Map getSingleUseRegisters(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) { + AVM2Code code = body.getCode(); + Map ret = new HashMap<>(); + + if (code.code.isEmpty()) { + return ret; + } + + ExecutionResult res = new ExecutionResult(); + visitCode(new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, res); + for (int reg : res.assignCount.keySet()) { + if (res.assignCount.get(reg) == 1) { + ret.put(reg, res.lastAssigned.get(reg)); + } + } + + return ret; + } + + private void visitCode(Set visited, TranslateStack stack, int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result) { + List output = new ArrayList<>(); + AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex); + localData.localRegs.put(0, new NullAVM2Item(null));//this + int instructionsProcessed = 0; + + try { + while (true) { + if (idx > endIdx) { + break; + } + if (visited.contains(idx)) { + break; + } + visited.add(idx); + + AVM2Instruction action = code.code.get(idx); + instructionsProcessed++; + + + /*if (action.definition instanceof GetLocalTypeIns) { + int regId = ((GetLocalTypeIns) action.definition).getRegisterId(action);//stack.peek().getResult().toString(); + if (!localData.localRegs.containsKey(regId)) { + break; + } + }*/ + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + InstructionDefinition def = action.definition; + + if (def instanceof SetLocalTypeIns) { + SetLocalTypeIns slt = (SetLocalTypeIns) def; + int regId = slt.getRegisterId(action); + if (!result.assignCount.containsKey(regId)) { + result.assignCount.put(regId, 0); + } + + result.assignCount.put(regId, result.assignCount.get(regId) + 1); + + GraphTargetItem regVal = localData.localRegs.get(regId); + if (regVal == null || !regVal.getNotCoerced().isCompileTime()) { + result.assignCount.put(regId, Integer.MAX_VALUE); + } else { + result.lastAssigned.put(regId, regVal.getNotCoerced()); + } + //assignCount + } + + idx++; + + if (action.definition instanceof JumpIns) { + + long address = action.offset + action.getBytes().length + action.operands[0]; + idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); + if (idx == -1) { + throw new TranslateException("Jump target not found: " + address); + } + } + + if (action.isBranch()) { + List branches = action.getBranches(new GraphSource() { + + @Override + public int size() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public GraphSourceItem get(int pos) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public boolean isEmpty() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public List translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public int adr2pos(long adr) { + return code.adr2pos(adr); + } + + @Override + public long pos2adr(int pos) { + return code.pos2adr(pos); + } + }); + idx = branches.get(0); + for (int n = 1; n < branches.size(); n++) { + visitCode(visited, (TranslateStack) stack.clone(), classIndex, isStatic, body, scriptIndex, abc, code, branches.get(n), endIdx, result); + } + } + /*if (action.definition instanceof IfTypeIns) { + long address = action.offset + action.getBytes().length + action.operands[0]; + int newIdx = code.adr2pos(address); + if (newIdx == -1) { + throw new TranslateException("If target not found: " + address); + } + visitCode(visited, (TranslateStack) stack.clone(), classIndex, isStatic, body, scriptIndex, abc, code, newIdx, endIdx, result); + }*/ + + if (action.definition instanceof ReturnValueIns) { + break; + } + + if (action.definition instanceof ThrowIns) { + break; + } + + if (action.definition instanceof ReturnVoidIns) { + break; + } + } + } catch (EmptyStackException | TranslateException | InterruptedException ex) { + ex.printStackTrace(); + } + } + + class ExecutionResult { + + public Map assignCount = new HashMap<>(); + public Map lastAssigned = new HashMap<>(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java index 1e21be20b..bfeabfa67 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; @@ -38,6 +39,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; @@ -48,6 +50,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns; import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; @@ -63,12 +66,15 @@ import com.jpexs.decompiler.flash.ecma.Undefined; import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateException; import com.jpexs.decompiler.graph.TranslateStack; import com.jpexs.decompiler.graph.model.FalseItem; +import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.graph.model.TrueItem; import java.util.ArrayList; import java.util.EmptyStackException; +import java.util.HashMap; import java.util.List; /** @@ -145,12 +151,10 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { if (code.code.size() == 0) { return false; } - System.err.println("====================================================="); for (int i = 0; i < code.code.size(); i++) { ExecutionResult result = new ExecutionResult(); - System.err.println("Execute from " + i); - executeActions(code, i, code.code.size() - 1, result); + executeActions(classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result); if (result.idx != -1) { int newIstructionCount = 1; // jump @@ -158,44 +162,59 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { newIstructionCount += result.stack.size(); } - if (newIstructionCount < result.instructionsProcessed) { + if (newIstructionCount < result.instructionsProcessed) //if (result.isIf) + { AVM2Instruction target = code.code.get(result.idx); AVM2Instruction prevAction = code.code.get(i); + int idelta = 0; if (result.stack.isEmpty() && prevAction.definition instanceof JumpIns) { - prevAction.operands[0] = ((int) (target.getOffset() - prevAction.getOffset() - prevAction.getBytes().length)); + prevAction.operands[0] = ((int) (target.offset - prevAction.offset - prevAction.getBytes().length)); } else { if (!result.stack.isEmpty()) { for (GraphTargetItem graphTargetItem : result.stack) { - AVM2Instruction ins = makePush(cpool, graphTargetItem); - if (ins != null) { - code.insertInstruction(i++, ins); + if (graphTargetItem instanceof PopItem) { + continue; + } + AVM2Instruction ins = makePush(graphTargetItem.getResult(), cpool); + if (ins != null) { + code.insertInstruction(i + (idelta++), ins); + //prevAction = ins; + } else { + throw new TranslateException("Cannot push: " + graphTargetItem); } - prevAction = ins; - //DirectValueActionItem dv = (DirectValueActionItem) graphTargetItem; - //push.values.add(dv.value); - } - //push.setAddress(prevAction.getAddress()); + } } AVM2Instruction jump = new AVM2Instruction(0, new JumpIns(), new int[]{0}); - jump.offset = prevAction.offset; - jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length)); - code.insertInstruction(i++, jump); - } + code.insertInstruction(i + (idelta++), jump); - AVM2Instruction nextAction = code.code.size() > i ? code.code.get(i) : null; + jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length)); + + } removeUnreachableActions(code, cpool, trait, minfo, body); removeZeroJumps(code, body); - if (nextAction != null) { - int nextIdx = code.code.indexOf(nextAction); - if (nextIdx < i) { - i = nextIdx; - } - } + i = -1; + /*if (nextAction != null) { + long mapped = nextAction.mappedOffset; + int nextIdx = -1; + for (int p = 0; p < code.code.size(); p++) { + if (code.code.get(p).mappedOffset == mapped) { + nextIdx = p; + break; + } + } + if (nextIdx == -1) { + //? + break; + } else { + i = nextIdx - 1; + } + + }*/ } } } @@ -220,9 +239,33 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { return result; } - private void executeActions(AVM2Code code, int idx, int endIdx, ExecutionResult result) { - List output = new ArrayList<>(); + protected AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool cpool, MethodBody body, boolean isStatic, int classIndex) { AVM2LocalData localData = new AVM2LocalData(); + localData.isStatic = isStatic; + localData.classIndex = classIndex; + localData.localRegs = new HashMap<>(); + localData.scopeStack = new ScopeStack(true); + localData.constants = cpool; + localData.methodInfo = abc.method_info; + localData.methodBody = body; + localData.abc = abc; + localData.localRegNames = new HashMap<>(); + localData.fullyQualifiedNames = new ArrayList<>(); + localData.parsedExceptions = new ArrayList<>(); + localData.finallyJumps = new HashMap<>(); + localData.ignoredSwitches = new HashMap<>(); + localData.ignoredSwitches2 = new ArrayList<>(); + localData.scriptIndex = scriptIndex; + localData.localRegAssignmentIps = new HashMap<>(); + localData.ip = 0; + localData.refs = new HashMap<>(); + localData.code = body.getCode(); + return localData; + } + + private void executeActions(int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result) { + List output = new ArrayList<>(); + AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex); FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(""); int instructionsProcessed = 0; @@ -238,12 +281,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { } AVM2Instruction action = code.code.get(idx); - - /*System.out.print(action.getASMSource(actions, new ArrayList(), ScriptExportMode.PCODE)); - for (int j = 0; j < stack.size(); j++) { - System.out.print(" '" + stack.get(j).getResult() + "'"); - } - System.out.println();*/ + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); InstructionDefinition def = action.definition; Class allowedDefs[] = new Class[]{ @@ -286,28 +324,34 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { if (!ok) { break; } - action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); - - idx++; + //boolean ifed = false; if (def instanceof JumpIns) { //ActionJump jump = (ActionJump) action; - long address = action.getOffset() + action.getBytes().length + action.operands[0]; + long address = action.offset + action.getBytes().length + action.operands[0]; idx = code.adr2pos(address); + if (idx == -1) { throw new TranslateException("Jump target not found: " + address); } - } - - if (def instanceof IfTypeIns) { + } else if (def instanceof IfTypeIns) { //ActionIf aif = (ActionIf) action; - if (EcmaScript.toBoolean(stack.pop().getResult())) { + GraphTargetItem top = stack.pop(); + Object res = top.getResult(); + if (EcmaScript.toBoolean(res)) { long address = action.offset + action.getBytes().length + action.operands[0]; idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); if (idx == -1) { throw new TranslateException("If target not found: " + address); } + //ifed = true; + } else { + //action.definition = new DeobfuscatePopIns(); + code.replaceInstruction(idx, new AVM2Instruction(action.offset, new DeobfuscatePopIns(), new int[]{}), body); + idx++; } + } else { + idx++; } instructionsProcessed++; @@ -318,8 +362,12 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { result.stack.clear(); result.stack.addAll(stack); } + } } catch (EmptyStackException | TranslateException | InterruptedException ex) { + //result.idx = -1; + //result.isIf = false; + //ignore } } @@ -341,7 +389,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { } - public void deobfuscate(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + public void deobfuscate(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); removeZeroJumps(body.getCode(), body); @@ -355,6 +403,5 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { public TranslateStack stack = new TranslateStack("?"); - public Object resultValue; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java index 57158d6a3..7fdc2075e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java @@ -39,6 +39,7 @@ import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.NotCompileTimeItem; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.PopItem; import java.util.HashMap; import java.util.List; import java.util.Stack; @@ -58,7 +59,9 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S } else { localRegs.put(regId, value); }*/ - localRegs.put(regId, value); + if (!(value instanceof PopItem)) { + localRegs.put(regId, value); + } if (!regAssignCount.containsKey(regId)) { regAssignCount.put(regId, 0); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/LocalRegAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/LocalRegAVM2Item.java index 36b178587..9dc5ef03d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/LocalRegAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/LocalRegAVM2Item.java @@ -90,7 +90,7 @@ public class LocalRegAVM2Item extends AVM2Item { @Override public boolean isCompileTime(Set dependencies) { - return isCT; + return false; //isCT; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java index 1156095b9..e8f6ba74b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java @@ -27,7 +27,7 @@ import java.util.Stack; /** * This class is a scanner generated by * JFlex 1.6.0 - * from the specification file C:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript3_script.flex + * from the specification file D:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript3_script.flex */ public final class ActionScriptLexer { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 303150337..1af07b3d3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -20,7 +20,8 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ABCInputStream; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscator; +import com.jpexs.decompiler.flash.abc.avm2.AVM2DeobfuscatorRegisters; +import com.jpexs.decompiler.flash.abc.avm2.AVM2DeobfuscatorSimple; import com.jpexs.decompiler.flash.abc.avm2.CodeStats; import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -202,6 +203,7 @@ public final class MethodBody implements Cloneable { if (exportMode != ScriptExportMode.AS) { getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer); } else { + //if (!path.contains("@")) { if (!Configuration.decompile.get()) { writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); return; @@ -245,6 +247,7 @@ public final class MethodBody implements Cloneable { if (exportMode != ScriptExportMode.AS) { getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer); } else { + //if (!path.contains("@")) { if (!Configuration.decompile.get()) { //writer.startMethod(this.method_info); writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); @@ -276,12 +279,19 @@ public final class MethodBody implements Cloneable { public MethodBody convertMethodBody(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, AVM2ConstantPool constants, List method_info, ScopeStack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, Traits initTraits) throws InterruptedException { MethodBody b = clone(); - AVM2Code deobfuscated = b.getCode(); - deobfuscated.markMappedOffsets(); - //deobfuscated.inlineJumpExit(); + b.getCode().markMappedOffsets(); + if (Configuration.autoDeobfuscate.get()) { - AVM2Deobfuscator deo = new AVM2Deobfuscator(); - deo.deobfuscate(classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b); + if (Configuration.deobfuscationMode.get() == 0) { + try { + b.getCode().removeTraps(constants, trait, method_info.get(this.method_info), b, abc, scriptIndex, classIndex, isStatic, path); + } catch (Throwable ex) { + logger.log(Level.SEVERE, "Error during old deobfuscation: " + path, ex); + } + } else { + new AVM2DeobfuscatorSimple().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b); + new AVM2DeobfuscatorRegisters().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b); + } } return b; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java index bb5478932..59f630cfd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java @@ -16,15 +16,17 @@ */ package com.jpexs.decompiler.graph; -import java.util.Stack; - /** * * @author JPEXS */ public class ScopeStack extends TranslateStack { + public ScopeStack(boolean allowEmpty) { + super(allowEmpty ? "scope" : null); + } + public ScopeStack() { - super("scope"); + this(true); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java index f9704f06f..58691a0b8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/FalseItem.java @@ -65,4 +65,14 @@ public class FalseItem extends GraphTargetItem implements LogicalOpItem, SimpleV return true; } + @Override + public boolean isCompileTime() { + return true; + } + + @Override + public Object getResult() { + return Boolean.FALSE; + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java index 99069a463..2421816a6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TrueItem.java @@ -65,4 +65,15 @@ public class TrueItem extends GraphTargetItem implements LogicalOpItem, SimpleVa public boolean isSimpleValue() { return true; } + + @Override + public boolean isCompileTime() { + return true; + } + + @Override + public Object getResult() { + return Boolean.TRUE; + } + } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java new file mode 100644 index 000000000..ff5e33f9a --- /dev/null +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.graph.CompilationException; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.concurrent.TimeoutException; +import static org.testng.Assert.fail; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript3DeobfuscatorTest extends ActionStript2TestBase { + + @BeforeClass + public void init() throws IOException, InterruptedException { + //Main.initLogging(false); + Configuration.autoDeobfuscate.set(true); + Configuration.deobfuscationMode.set(1); + swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false); + } + + private String recompile(String str) throws AVM2ParseException, IOException, CompilationException, InterruptedException { + str = "package { public class Test { public static function trace(s){ } public static function test(){ " + str + " } } }"; + final ABC abc = new ABC(new ABCContainerTag() { + + @Override + public ABC getABC() { + return null; + } + + @Override + public SWF getSwf() { + return swf; + } + + @Override + public int compareTo(ABCContainerTag o) { + return 0; + } + }); + ActionScriptParser par = new ActionScriptParser(abc, new ArrayList<>()); + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + par.addScript(str, true, "Test.as", 0); + + abc.script_info.get(0).getPacks(abc, 0, "", new ArrayList<>()).get(0).toSource(writer, abc.script_info.get(0).traits.traits, ScriptExportMode.AS, false); + return writer.toString(); + } + + @DataProvider(name = "provideBasicTrueExpressions") + public Object[][] provideBasicTrueExpressions() { + return new Object[][]{ + {"1!=5"}, {"5==5"}, {"1<4"}, {"5>4"}, {"5*6==30"} + }; + } + + @DataProvider(name = "provideBasicFalseExpressions") + public Object[][] provideBasicFalseExpressions() { + return new Object[][]{ + {"1==5"}, {"5!=5"}, {"1>4"}, {"5<4"}, {"5*7==12"} + }; + } + + @Test(dataProvider = "provideBasicTrueExpressions") + public void testRemoveBasicTrueExpressions(String expression) throws IOException, CompilationException, InterruptedException, TimeoutException, AVM2ParseException { + String res = recompile("if(" + expression + "){" + + "trace(\"OK\");" + + "} else {" + + "trace(\"FAIL\");" + + "}"); + if (res.contains("\"FAIL\"")) { + fail("OnFalse clause was not removed: " + res); + } + if (!res.contains("\"OK\"")) { + fail("OnTrue clause was removed: " + res); + } + } + + @Test(dataProvider = "provideBasicFalseExpressions") + public void testRemoveBasicFalseExpressions(String expression) throws Exception { + String res = recompile("if(" + expression + "){" + + "trace(\"FAIL\");" + + "} else {" + + "trace(\"OK\");" + + "}"); + if (res.contains("\"FAIL\"")) { + fail("OnTrue clause was not removed:" + res); + } + if (!res.contains("\"OK\"")) { + fail("OnFalse clause was removed:" + res); + } + } + + @Test + public void testRemoveKnownVariables() throws Exception { + String res = recompile("var a = true; var b = false;" + + "if(a){" + + "trace(\"OK1\");" + + "}else{" + + "trace(\"FAIL1\");" + + "}" + + "if(b){" + + "trace(\"FAIL2\");" + + "}else{" + + "trace(\"OK2\");" + + "}"); + if (!res.contains("\"OK1\"")) { + fail("if true OnTrue removed"); + } + if (!res.contains("\"OK2\"")) { + fail("if false OnFalse removed" + res); + } + if (res.contains("\"FAIL1\"")) { + fail("if true OnFalse not removed"); + } + if (res.contains("\"FAIL2\"")) { + fail("if false OnTrue not removed"); + } + if (res.contains("var ")) { + fail("variables for obsucation not removed"); + } + if (res.contains("if")) { + fail("if clauses not removed"); + } + } + + @Test + public void testRemoveKnownVariables2() throws Exception { + String res = recompile("var a = true; var b = false;" + + "if(a){" + + "trace(\"OK1\");" + + "}else{" + + "trace(\"OK2\");" + + "}" + + "a = 59;" + + "if(b){" + + "trace(\"FAIL1\");" + + "}else{" + + "trace(\"OK3\");" + + "}"); + if (!res.contains("\"OK1\"")) { + fail("!OK1:" + res); + } + if (!res.contains("\"OK2\"")) { + fail("!OK2"); + } + if (!res.contains("\"OK3\"")) { + fail("!OK3"); + } + if (res.contains("\"FAIL1\"")) { + fail("FAIL1"); + } + } + + // TODO: JPEXS @Test + public void testNotRemoveParams() throws Exception { + String res = recompile("function tst(p1,p2){" + + "var a = 2;" + + "var b = 3 * a;" + + "if(b>1){" + + "trace(\"OK1\");" + + "}else{" + + "trace(\"FAIL1\");" + + "}" + + "var c = p1*5;" + + "if(c){" + + "trace(\"OK2\");" + + "}else{" + + "trace(\"OK3\");" + + "}" + + "}"); + if (!res.contains("\"OK1\"")) { + fail("basic if true onTrue removed"); + } + if (res.contains("\"FAIL1\"")) { + fail("basic if true onFalse not removed"); + } + if (!res.contains("\"OK2\"")) { + fail("if parameter onTrue removed"); + } + if (!res.contains("\"OK3\"")) { + fail("if parameter onFalse removed"); + } + } + + //TODO: JPEXS @Test + public void testEvailExpressionAfterWhile() throws Exception { + String res = recompile("var a = 5;" + + "while(true){" + + "if(a==73){" + + "a = 15;" + + "}" + + "if(a==1){" + + "trace(\"FAIL1\");" + + "}" + + "if(a==5){" + + "a=50;" + + "}" + + "if(a == 201){" + + "break;" + + "}" + + "a++;" + + "if(a == 53){" + + "a = a + 20;" + + "}" + + "if(a>500){" + + "trace(\"FAIL2\");" + + "}" + + "if(a==16){" + + "a = 200;" + + "}" + + "}" + + "" + + "if(a == 201){" + + "trace(\"OK\");" + + "}else{" + + "trace(\"FAIL3\");" + + "}"); + if (res.contains("\"FAIL1\"")) { + fail("unreachable if onTrue not removed"); + } + if (res.contains("\"FAIL2\"")) { + fail("unreachable if onTrue 2 not removed"); + } + if (res.contains("\"FAIL3\"")) { + fail("unreachable if onTrue 3 not removed"); + } + if (!res.contains("\"OK\"")) { + fail("reachable of onTrue removed"); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index b37c480b4..c4de988e2 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -497,7 +497,7 @@ contextmenu.parseABC = Parse ABC contextmenu.parseInstructions = Parse AVM2 Instructions #after version 2.1.3 -menu.deobfuscation = AS1/2 Deobfuscation +menu.deobfuscation = Deobfuscation menu.file.deobfuscation.old = Old style menu.file.deobfuscation.new = New style diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_ca.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_ca.properties index 86879963b..83d1aef65 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_ca.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_ca.properties @@ -497,7 +497,7 @@ contextmenu.parseABC = Analitza ABC contextmenu.parseInstructions = Analitza les instruccions AVM2 #after version 2.1.3 -menu.deobfuscation = Desofuscaci\u00f3 AS1/2 +menu.deobfuscation = Desofuscaci\u00f3 menu.file.deobfuscation.old = Estil vell menu.file.deobfuscation.new = Estil nou diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index c38a772fc..5c86b17fd 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -496,7 +496,7 @@ contextmenu.parseActions = Naparsovat akce contextmenu.parseABC = Naparsovat ABC contextmenu.parseInstructions = Naparsovat AVM2 instrukce -menu.deobfuscation = AS1/2 Deobfuskace +menu.deobfuscation = Deobfuskace menu.file.deobfuscation.old = Star\u00fd zp\u016fsob menu.file.deobfuscation.new = Nov\u00fd zp\u016fsob diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_es.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_es.properties index 7017ceaab..344a0c9fe 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_es.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_es.properties @@ -497,7 +497,7 @@ contextmenu.parseABC = Analizar ABC contextmenu.parseInstructions = Analizar instrucciones AVM2 #after version 2.1.3 -menu.deobfuscation = Desofuscaci\u00f3n AS1/2 +menu.deobfuscation = Desofuscaci\u00f3n menu.file.deobfuscation.old = Estilo viejo menu.file.deobfuscation.new = Estilo nuevo diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_fr.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_fr.properties index b33b1be20..710801368 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_fr.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_fr.properties @@ -497,7 +497,7 @@ contextmenu.parseABC = Analyser ABC contextmenu.parseInstructions = Analyser les instructions AVM2 #after version 2.1.3 -menu.deobfuscation = AS1/2 D\u00e9sobfuscation +menu.deobfuscation = D\u00e9sobfuscation menu.file.deobfuscation.old = Ancien style menu.file.deobfuscation.new = Nouveau style diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties index 6048ba5d5..f7ca6666f 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties @@ -497,7 +497,7 @@ contextmenu.parseABC = ABC elemz\u00e9se contextmenu.parseInstructions = AVM2 utas\u00edt\u00e1sok elemz\u00e9se #after version 2.1.3 -menu.deobfuscation = AS1/2 Deobfuszk\u00e1l\u00e1s +menu.deobfuscation = Deobfuszk\u00e1l\u00e1s menu.file.deobfuscation.old = R\u00e9gi menu.file.deobfuscation.new = \u00daj diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_pl.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_pl.properties index 63ec9aa4e..81bf6231c 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_pl.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_pl.properties @@ -495,7 +495,7 @@ contextmenu.parseActions = Analizuj akcje contextmenu.parseABC = Analizuj ABC contextmenu.parseInstructions = Analizuj instrukcje AVM2 -menu.deobfuscation = Odkodowanie AS1/2 +menu.deobfuscation = Odkodowanie menu.file.deobfuscation.old = Stary styl menu.file.deobfuscation.new = Nowy styl diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_ru.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_ru.properties index 1dc7de3dd..0bbcef832 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_ru.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_ru.properties @@ -1,578 +1,578 @@ -# Copyright (C) 2010-2015 JPEXS -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -menu.file = \u0424\u0430\u0439\u043b -menu.file.open = \u041e\u0442\u043a\u0440\u044b\u0442\u044c... -menu.file.save = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -menu.file.saveas = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a... -menu.file.export.fla = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 FLA -menu.file.export.all = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0451 -menu.file.export.selection = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 -menu.file.exit = \u0412\u044b\u0439\u0442\u0438 - -menu.tools = \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b -menu.tools.searchas = \u041f\u043e\u0438\u0441\u043a \u043f\u043e \u0432\u0441\u0435\u043c\u0443 ActionScript... -menu.tools.proxy = \u041f\u0440\u043e\u043a\u0441\u0438 -menu.tools.deobfuscation = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f -menu.tools.deobfuscation.pcode = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f P-code... -menu.tools.deobfuscation.globalrename = \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 -menu.tools.deobfuscation.renameinvalid = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b -menu.tools.gotoDocumentClass = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443 - -menu.settings = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 -menu.settings.autodeobfuscation = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f -menu.settings.internalflashviewer = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u044c Flash -menu.settings.parallelspeedup = \u041c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c (\u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b) -menu.settings.disabledecompilation = \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0438\u0437\u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c) -menu.settings.addtocontextmenu = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c FFDec \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435 \u043c\u0435\u043d\u044e SWF \u0444\u0430\u0439\u043b\u043e\u0432 -menu.settings.language = \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u044f\u0437\u044b\u043a -menu.settings.cacheOnDisk = \u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0434\u0438\u0441\u043a -menu.settings.gotoMainClassOnStartup = \u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 - -menu.help = \u041f\u043e\u043c\u043e\u0449\u044c -menu.help.checkupdates = \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f... -menu.help.helpus = \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043d\u0430\u0441! -menu.help.homepage = \u0414\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 -menu.help.about = \u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435... - -contextmenu.remove = \u0423\u0434\u0430\u043b\u0438\u0442\u044c - -button.save = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -button.edit = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c -button.cancel = \u041e\u0442\u043c\u0435\u043d\u0430 -button.replace = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c... - -notavailonthisplatform = \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f Windows). - -swfpreview = \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 SWF -swfpreview.internal = \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 SWF (\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u044c) - -parameters = \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b - -rename.enternew = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u0438\u043c\u044f: - -rename.finished.identifier = \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d. -rename.finished.multiname = %count% multiname \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043e. - -node.texts = \u0442\u0435\u043a\u0441\u0442\u044b -node.images = \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f -node.movies = \u0432\u0438\u0434\u0435\u043e -node.sounds = \u0437\u0432\u0443\u043a\u0438 -node.binaryData = \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 -node.fonts = \u0448\u0440\u0438\u0444\u0442\u044b -node.sprites = \u0441\u043f\u0440\u0430\u0439\u0442\u044b -node.shapes = \u0444\u043e\u0440\u043c\u044b -node.morphshapes = morphshapes -node.buttons = \u043a\u043d\u043e\u043f\u043a\u0438 -node.frames = \u043a\u0430\u0434\u0440\u044b -node.scripts = \u0441\u043a\u0440\u0438\u043f\u0442\u044b - -message.warning = \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 -message.confirm.experimental = \u041f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0432\u0440\u0435\u0434\u0438\u0442\u044c SWF \u0444\u0430\u0439\u043b \u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0438\u043c.\r\n\u0418\u0421\u041f\u041e\u041b\u042c\u0417\u0423\u0419\u0422\u0415 \u041d\u0410 \u0421\u0412\u041e\u0419 \u0421\u0422\u0420\u0410\u0425 \u0418 \u0420\u0418\u0421\u041a! \u0412\u044b \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? -message.confirm.parallel = \u041c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0436\u0435\u0442 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0438 \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e, \u043d\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0430\u043c\u044f\u0442\u0438. -message.confirm.on = \u0412\u041a\u041b\u044e\u0447\u0438\u0442\u044c? -message.confirm.off = \u0412\u042b\u041a\u041b\u044e\u0447\u0438\u0442\u044c? -message.confirm = \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c - -message.confirm.autodeobfuscate = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0444\u0443\u0441\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434.\r\n\u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u0435\u0442 \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \"\u043c\u0451\u0440\u0442\u0432\u043e\u0433\u043e\" \u043a\u043e\u0434\u0430.\r\n\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e \u043b\u0443\u0447\u0448\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u043a\u043e\u0434 \u043d\u0435 \u043e\u0431\u0444\u0443\u0441\u0446\u0438\u0440\u043e\u0432\u0430\u043d. - -message.parallel = \u041c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c -message.trait.saved = Trait \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d - -message.constant.new.string = \u0421\u0442\u0440\u043e\u043a\u0430 (String) "%value%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c? -message.constant.new.string.title = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 (String) -message.constant.new.integer = \u0426\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Integer) "%value%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c? -message.constant.new.integer.title = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Integer) -message.constant.new.unsignedinteger = \u0411\u0435\u0437\u0437\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Unsigned integer) "%value%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c? -message.constant.new.unsignedinteger.title = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0435\u0437\u0437\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Unsigned integer) -message.constant.new.double = \u0414\u0440\u043e\u0431\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Double) "%value%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c? -message.constant.new.double.title = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Double) - -work.buffering = \u0411\u0443\u0444\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f -work.waitingfordissasembly = \u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0434\u0438\u0437\u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f -work.gettinghilights = \u041f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 -work.disassembling = \u0414\u0438\u0437\u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 -work.exporting = \u042d\u043a\u0441\u043f\u043e\u0440\u0442 -work.searching = \u041f\u043e\u0438\u0441\u043a -work.renaming = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 -work.exporting.fla = \u042d\u043a\u0441\u043f\u043e\u0440\u0442 FLA -work.renaming.identifiers = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 -work.deobfuscating = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f -work.decompiling = \u0414\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f -work.gettingvariables = \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 -work.reading.swf = \u0427\u0442\u0435\u043d\u0438\u0435 SWF -work.creatingwindow = \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u043a\u043d\u0430 -work.buildingscripttree = \u041f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0434\u0435\u0440\u0435\u0432\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 - -work.deobfuscating.complete = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430 - -message.search.notfound = \u0422\u0435\u043a\u0441\u0442 "%searchtext%" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d. -message.search.notfound.title = \u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e - -message.rename.notfound.multiname = \u041f\u043e\u0434 \u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c multiname -message.rename.notfound.identifier = \u041f\u043e\u0434 \u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 -message.rename.notfound.title = \u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e -message.rename.renamed = \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043e: %count% - -filter.images = \u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f (*.jpg,*.gif,*.png,*.bmp) -filter.fla = \u041f\u0440\u043e\u0435\u043a\u0442 %version% (*.fla) -filter.xfl = \u041d\u0435\u0441\u0436\u0430\u0442\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 %version% (*.xfl) -filter.swf = SWF \u0444\u0430\u0439\u043b\u044b (*.swf) - -error = \u041e\u0448\u0438\u0431\u043a\u0430 -error.image.invalid = \u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435. - -error.text.invalid = \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442: %text% \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 %line% -error.file.save = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0444\u0430\u0439\u043b -error.file.write = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0444\u0430\u0439\u043b -error.export = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 - -export.select.directory = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 -export.finishedin = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0437\u0430 %time% - -update.check.title = \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 -update.check.nonewversion = \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043d\u0435\u0442. - -message.helpus = \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\r\n%url%\r\n\u0434\u043b\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0435\u0439. -message.homepage = \u041f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443: \r\n%url% - -proxy = \u041f\u0440\u043e\u043a\u0441\u0438 -proxy.start = \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438 -proxy.stop = \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438 -proxy.show = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438 -exit = \u0412\u044b\u0439\u0442\u0438 - -panel.disassembled = P-\u043a\u043e\u0434 -panel.decompiled = ActionScript - -search.info = \u041f\u043e\u0438\u0441\u043a "%text%": -search.script = \u0421\u043a\u0440\u0438\u043f\u0442 - -constants = Constants -traits = Traits - -pleasewait = \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435 - -abc.detail.methodtrait = Method/Getter/Setter Trait -abc.detail.unsupported = - -abc.detail.slotconsttrait = Slot/Const Trait -abc.detail.traitname = \u0418\u043c\u044f: - -abc.detail.body.params.maxstack = \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0442\u0435\u043a\u0430: -abc.detail.body.params.localregcount = \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432: -abc.detail.body.params.minscope = \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438: -abc.detail.body.params.maxscope = \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438: -abc.detail.body.params.autofill = \u0410\u0432\u0442\u043e\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043a\u043e\u0434\u0430 (\u0413\u041b\u041e\u0411\u0410\u041b\u042c\u041d\u0410\u042f \u041d\u0410\u0421\u0422\u0420\u041e\u0419\u041a\u0410) -abc.detail.body.params.autofill.experimental = ...\u042d\u041a\u0421\u041f\u0415\u0420\u0418\u041c\u0415\u041d\u0422\u0410\u041b\u042c\u041d\u041e - -abc.detail.methodinfo.methodindex = \u0418\u043d\u0434\u0435\u043a\u0441 \u043c\u0435\u0442\u043e\u0434\u0430: -abc.detail.methodinfo.parameters = \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b: -abc.detail.methodinfo.returnvalue = \u0422\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f: - -error.methodinfo.params = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445 MethodInfo -error.methodinfo.returnvalue = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0442\u0438\u043f\u0435 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f MethodInfo - -abc.detail.methodinfo = MethodInfo -abc.detail.body.code = \u041a\u043e\u0434 MethodBody -abc.detail.body.params = \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b MethodBody - -abc.detail.slotconst.typevalue = \u0422\u0438\u043f \u0438 \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435: - -error.slotconst.typevalue = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0442\u0438\u043f\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f SlotConst - -message.autofill.failed = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432.\r\n\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. -info.selecttrait = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u043b\u0430\u0441\u0441 \u0438 \u043a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u043d\u0430 trait \u0432 ActionScript \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. - -button.viewgraph = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0413\u0440\u0430\u0444\u0430 -button.viewhex = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 Hex - -abc.traitslist.instanceinitializer = \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 -abc.traitslist.classinitializer = \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 - -action.edit.experimental = (\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e) - -message.action.saved = \u041a\u043e\u0434 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d - -error.action.save = %error% \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 %line% - -message.confirm.remove = \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 %item%\n \u0438 \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u043e\u0442 \u043d\u0435\u0433\u043e? - -#after version 1.6.5u1: - -button.ok = OK -button.cancel = \u041e\u0442\u043c\u0435\u043d\u0430 - -font.name = \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0448\u0440\u0438\u0444\u0442\u0430: -font.isbold = \u0416\u0438\u0440\u043d\u044b\u0439: -font.isitalic = \u041a\u0443\u0440\u0441\u0438\u0432: -font.ascent = \u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0432\u044b\u043d\u043e\u0441: -font.descent = \u041d\u0438\u0436\u043d\u0438\u0439 \u0432\u044b\u043d\u043e\u0441: -font.leading = \u0418\u043d\u0442\u0435\u0440\u043b\u0438\u043d\u044c\u044f\u0436: -font.characters = \u0421\u0438\u043c\u0432\u043e\u043b\u044b: -font.characters.add = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0438\u043c\u0432\u043e\u043b\u044b: -value.unknown = ? - -yes = \u0434\u0430 -no = \u043d\u0435\u0442 - -errors.present = \u0412 \u043b\u043e\u0433\u0435 \u0435\u0441\u0442\u044c \u041e\u0428\u0418\u0411\u041a\u0418. \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. -errors.none = \u0412 \u043b\u043e\u0433\u0435 \u043d\u0435\u0442 \u043e\u0448\u0438\u0431\u043e\u043a. - -#after version 1.6.6: - -dialog.message.title = \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 -dialog.select.title = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 - -button.yes = \u0414\u0430 -button.no = \u041d\u0435\u0442 - -FileChooser.openButtonText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c -FileChooser.openButtonToolTipText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c -FileChooser.lookInLabelText = \u0418\u0441\u043a\u0430\u0442\u044c \u0432: -FileChooser.acceptAllFileFilterText = \u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b -FileChooser.filesOfTypeLabelText = \u0422\u0438\u043f \u0444\u0430\u0439\u043b\u043e\u0432: -FileChooser.fileNameLabelText = \u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430: -FileChooser.listViewButtonToolTipText = \u0421\u043f\u0438\u0441\u043e\u043a -FileChooser.listViewButtonAccessibleName = \u0421\u043f\u0438\u0441\u043e\u043a -FileChooser.detailsViewButtonToolTipText = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 -FileChooser.detailsViewButtonAccessibleName = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 -FileChooser.upFolderToolTipText = \u0412\u0432\u0435\u0440\u0445 -FileChooser.upFolderAccessibleName = \u0412\u0432\u0435\u0440\u0445 -FileChooser.homeFolderToolTipText = \u0414\u043e\u043c\u043e\u0439 -FileChooser.homeFolderAccessibleName = \u0414\u043e\u043c\u043e\u0439 -FileChooser.fileNameHeaderText = \u0418\u043c\u044f -FileChooser.fileSizeHeaderText = \u0420\u0430\u0437\u043c\u0435\u0440 -FileChooser.fileTypeHeaderText = \u0422\u0438\u043f -FileChooser.fileDateHeaderText = \u0414\u0430\u0442\u0430 -FileChooser.fileAttrHeaderText = \u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b -FileChooser.openDialogTitleText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c -FileChooser.directoryDescriptionText = \u041f\u0430\u043f\u043a\u0430 -FileChooser.directoryOpenButtonText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c -FileChooser.directoryOpenButtonToolTipText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 -FileChooser.fileDescriptionText = \u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b -FileChooser.helpButtonText = \u041f\u043e\u043c\u043e\u0449\u044c -FileChooser.helpButtonToolTipText = \u041f\u043e\u043c\u043e\u0449\u044c \u043f\u043e \u0434\u0438\u0430\u043b\u043e\u0433\u0443 \u0432\u044b\u0431\u043e\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 -FileChooser.newFolderAccessibleName = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 -FileChooser.newFolderErrorText = \u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 -FileChooser.newFolderToolTipText = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443 -FileChooser.other.newFolder = \u041d\u043e\u0432\u0430\u044f\u041f\u0430\u043f\u043a\u0430 -FileChooser.other.newFolder.subsequent = \u041d\u043e\u0432\u0430\u044f\u041f\u0430\u043f\u043a\u0430.{0} -FileChooser.win32.newFolder = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 -FileChooser.win32.newFolder.subsequent = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 ({0}) -FileChooser.saveButtonText = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -FileChooser.saveButtonToolTipText = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b -FileChooser.saveDialogTitleText = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -FileChooser.saveInLabelText = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432: -FileChooser.updateButtonText = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c -FileChooser.updateButtonToolTipText = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0430\u043f\u043a\u0438 - -#after version 1.6.6u2: - -FileChooser.detailsViewActionLabel.textAndMnemonic = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 -FileChooser.detailsViewButtonToolTip.textAndMnemonic = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 -FileChooser.fileAttrHeader.textAndMnemonic = \u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b -FileChooser.fileDateHeader.textAndMnemonic = \u0418\u0437\u043c\u0435\u043d\u0435\u043d -FileChooser.fileNameHeader.textAndMnemonic = \u0418\u043c\u044f -FileChooser.fileNameLabel.textAndMnemonic = \u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430: -FileChooser.fileSizeHeader.textAndMnemonic = \u0420\u0430\u0437\u043c\u0435\u0440 -FileChooser.fileTypeHeader.textAndMnemonic = \u0422\u0438\u043f -FileChooser.filesOfTypeLabel.textAndMnemonic = \u0424\u0430\u0439\u043b\u044b \u0442\u0438\u043f\u0430: -FileChooser.folderNameLabel.textAndMnemonic = \u0418\u043c\u044f \u043f\u0430\u043f\u043a\u0438: -FileChooser.homeFolderToolTip.textAndMnemonic = \u0414\u043e\u043c\u043e\u0439 -FileChooser.listViewActionLabel.textAndMnemonic = \u0421\u043f\u0438\u0441\u043e\u043a -FileChooser.listViewButtonToolTip.textAndMnemonic = \u0421\u043f\u0438\u0441\u043e\u043a -FileChooser.lookInLabel.textAndMnemonic = \u0418\u0441\u043a\u0430\u0442\u044c \u0432: -FileChooser.newFolderActionLabel.textAndMnemonic = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 -FileChooser.newFolderToolTip.textAndMnemonic = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443 -FileChooser.refreshActionLabel.textAndMnemonic = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c -FileChooser.saveInLabel.textAndMnemonic = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432: -FileChooser.upFolderToolTip.textAndMnemonic = \u0412\u0432\u0435\u0440\u0445 -FileChooser.viewMenuButtonAccessibleName = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u041c\u0435\u043d\u044e -FileChooser.viewMenuButtonToolTipText = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u041c\u0435\u043d\u044e -FileChooser.viewMenuLabel.textAndMnemonic = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 -FileChooser.newFolderActionLabelText = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 -FileChooser.listViewActionLabelText = \u0421\u043f\u0438\u0441\u043e\u043a -FileChooser.detailsViewActionLabelText = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 -FileChooser.refreshActionLabelText = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c -FileChooser.sortMenuLabelText = \u0423\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u043a\u0438 -FileChooser.viewMenuLabelText = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 -FileChooser.fileSizeKiloBytes = {0} \u041a\u0411 -FileChooser.fileSizeMegaBytes = {0} \u041c\u0411 -FileChooser.fileSizeGigaBytes = {0} \u0413\u0411 -FileChooser.folderNameLabelText = \u0418\u043c\u044f \u043f\u0430\u043f\u043a\u0438: - -error.occured = \u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430: %error% -button.abort = \u041f\u0440\u0435\u0440\u0432\u0430\u0442\u044c -button.retry = \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c -button.ignore = \u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c - -font.source = \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u0448\u0440\u0438\u0444\u0442\u0430: - -#after version 1.6.7: - -menu.export = \u042d\u043a\u0441\u043f\u043e\u0440\u0442 -menu.general = \u041e\u0431\u0449\u0438\u0435 -menu.language = \u042f\u0437\u044b\u043a - -startup.welcometo = \u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 -startup.selectopen = \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u043e\u043a "\u041e\u0442\u043a\u0440\u044b\u0442\u044c" \u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435 SWF \u0444\u0430\u0439\u043b \u0432 \u044d\u0442\u043e \u043e\u043a\u043d\u043e. - -error.font.nocharacter = \u0421\u0438\u043c\u0432\u043e\u043b "%char%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c \u0448\u0440\u0438\u0444\u0442\u0435. - -warning.initializers = \u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430\u0445.\n\u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0445 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0434\u0435\u0441\u044c, \u043d\u043e \u0438 \u0442\u0430\u043c! - -#after version 1.7.0u1: - -menu.tools.searchMemory = \u0418\u0441\u043a\u0430\u0442\u044c SWF \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 -menu.file.reload = \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c -message.confirm.reload = \u042d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u043d\u0435\u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043d\u043e\u0432\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 SWF \u0444\u0430\u0439\u043b.\n \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? - -dialog.selectbkcolor.title = \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u0444\u043e\u043d\u0430 \u0434\u043b\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 SWF -button.selectbkcolor.hint = \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u0444\u043e\u043d\u0430 - -ColorChooser.okText = \u041e\u041a -ColorChooser.cancelText = \u041e\u0442\u043c\u0435\u043d\u0430 -ColorChooser.resetText = \u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c -ColorChooser.previewText = \u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 -ColorChooser.swatchesNameText = \u041e\u0431\u0440\u0430\u0437\u0446\u044b -ColorChooser.swatchesRecentText = \u041d\u0435\u0434\u0430\u0432\u043d\u0435\u0435: -ColorChooser.sampleText = \u041f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0434\u043f\u0438\u0441\u0438 \u041f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0434\u043f\u0438\u0441\u0438 - -#after version 1.7.1: - -preview.play = \u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 -preview.pause = \u041f\u0430\u0443\u0437\u0430 -preview.stop = \u0421\u0442\u043e\u043f - -message.confirm.removemultiple = \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435: %count%\n \u0438 \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u043e\u0442 \u043d\u0438\u0445? - -menu.tools.searchCache = \u041f\u043e\u0438\u0441\u043a \u0432 \u043a\u044d\u0448\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 - -#after version 1.7.2u2 - -error.trait.exists = Trait \u0441 \u0438\u043c\u0435\u043d\u0435\u043c "%name%" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. -button.addtrait = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c trait -button.font.embed = \u0412\u0441\u0442\u0440\u043e\u0438\u0442\u044c... -button.yes.all = \u0414\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 -button.no.all = \u041d\u0435\u0442 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 -message.font.add.exists = \u0421\u0438\u043c\u0432\u043e\u043b %char% \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u044d\u0433\u0435 \u0448\u0440\u0438\u0444\u0442\u0430.\n\u0416\u0435\u043b\u0430\u0435\u0442\u0435 \u043b\u0438 \u0412\u044b \u0435\u0433\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c? - -filter.gfx = GFx \u0444\u0430\u0439\u043b\u044b ScaleForm (*.gfx) -filter.supported = \u0412\u0441\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b -work.canceled = \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u043e -work.restoringControlFlow = \u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 -menu.advancedsettings.advancedsettings = \u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 -menu.recentFiles = \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u044b - -#after version 1.7.4 -work.restoringControlFlow.complete = \u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d -message.confirm.recentFileNotFound = \u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d. \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0435\u0433\u043e \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432? -contextmenu.closeSwf = \u0417\u0430\u043a\u0440\u044b\u0442\u044c SWF -menu.settings.autoRenameIdentifiers = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b -menu.file.saveasexe = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a Exe... -filter.exe = \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (*.exe) - -#after version 1.8.0 -font.updateTexts = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0430\u0434\u043f\u0438\u0441\u0438 - -#after version 1.8.0u1 -menu.file.close = \u0417\u0430\u043a\u0440\u044b\u0442\u044c -menu.file.closeAll = \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 -menu.tools.otherTools = \u0414\u0440\u0443\u0433\u043e\u0435 -menu.tools.otherTools.clearRecentFiles = \u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 -fontName.name = \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0448\u0440\u0438\u0444\u0442\u0430: -fontName.copyright = \u0410\u0432\u0442\u043e\u0440\u0441\u043a\u043e\u0435 \u043f\u0440\u0430\u0432\u043e: -button.preview = \u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 -button.reset = \u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c -errors.info = \u0412 \u043b\u043e\u0433\u0435 \u0435\u0441\u0442\u044c \u0432\u0430\u0436\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. -errors.warning = \u0412 \u043b\u043e\u0433\u0435 \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f! \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. - -decompilationError = \u041e\u0448\u0438\u0431\u043a\u0430 \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 - -disassemblingProgress.toString = \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u043e\u043a -disassemblingProgress.reading = \u0427\u0442\u0435\u043d\u0438\u0435 -disassemblingProgress.deobfuscating = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f - -contextmenu.moveTag = \u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0442\u044d\u0433 - -filter.swc = SWC \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 (*.swc) -filter.zip = ZIP \u0430\u0440\u0445\u0438\u0432\u044b (*.zip) -filter.binary = \u0411\u0438\u043d\u0430\u0440\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a - \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b (*.*) - -open.error = \u041e\u0448\u0438\u0431\u043a\u0430 -open.error.fileNotFound = \u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d -open.error.cannotOpen = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0444\u0430\u0439\u043b - -node.others = \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 - -#after version 1.8.1 -menu.tools.search = \u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430 - -#after version 1.8.1u1 -menu.tools.timeline = Timeline - -dialog.selectcolor.title = \u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u0430 -button.selectcolor.hint = \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0446\u0432\u0435\u0442\u0430 - -#default item name, will be used in following sentences -generictag.array.item = \u044d\u043b\u0435\u043c\u0435\u043d\u0442 -generictag.array.insertbeginning = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c %item% \u0432 \u043d\u0430\u0447\u0430\u043b\u043e -generictag.array.insertbefore = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c %item% \u043f\u0435\u0440\u0435\u0434 -generictag.array.remove = \u0423\u0434\u0430\u043b\u0438\u0442\u044c %item% -generictag.array.insertafter = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c %item% \u043f\u043e\u0441\u043b\u0435 -generictag.array.insertend = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c %item% \u0432 \u043a\u043e\u043d\u0435\u0446 - -#after version 2.0.0 -contextmenu.expandAll = \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u0441\u0435 - -filter.sounds = \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0437\u0432\u0443\u043a\u043e\u0432\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b (*.wav,*.mp3) -filter.sounds.wav = Wave \u0444\u043e\u0440\u043c\u0430\u0442 (*.wav) -filter.sounds.mp3 = MP3 \u0441\u0436\u0430\u0442\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 (*.mp3) - -error.sound.invalid = \u041d\u0435 \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 \u0437\u0432\u0443\u043a. - -button.prev = \u041d\u0430\u0437\u0430\u0434 -button.next = \u0414\u0430\u043b\u0435\u0435 - -#after version 2.1.0 -message.action.playerglobal.title = \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 PlayerGlobal -message.action.playerglobal.needed = \u0414\u043b\u044f \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f ActionScript 3 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 "PlayerGlobal.swc" \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Adobe.\r\n%adobehomepage%\r\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 OK, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044e. -message.action.playerglobal.place = \u0421\u043a\u0430\u0447\u0430\u0439\u0442\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 PlayerGlobal(.swc), \u0438 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u0435 \u0435\u0435 \u0432 \u043f\u0430\u043f\u043a\u0435\r\n%libpath%\r\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 OK \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f. - -message.confirm.experimental.function = \u042d\u0442\u043e \u042d\u041a\u0421\u041f\u0415\u0420\u0418\u041c\u0415\u041d\u0422\u0410\u041b\u042c\u041d\u0410\u042f \u0444\u0443\u043d\u043a\u0446\u0438\u044f. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0432\u0430\u043c \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0434\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c \u0438 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 swf \u0444\u0430\u0439\u043b \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e. -message.confirm.donotshowagain = \u041d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 - -menu.import = \u0418\u043d\u043f\u043e\u0440\u0442 -menu.file.import.text = \u0418\u043c\u043f\u043e\u0440\u0442 \u0442\u0435\u043a\u0441\u0442\u0430 -import.select.directory = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 -error.text.import = \u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 \u0442\u0435\u043a\u0441\u0442\u0430. \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? - -#after version 2.1.1 -contextmenu.removeWithDependencies = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 - -abc.action.find-usages = \u041d\u0430\u0439\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f -abc.action.find-declaration = \u041d\u0430\u0439\u0442\u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 - -contextmenu.rawEdit = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0430\u0439\u0442\u044b -contextmenu.jumpToCharacter = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u0438\u043c\u0432\u043e\u043b\u0443 - -menu.settings.dumpView = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u043e\u0431\u0440\u0430\u0437\u0430 - -menu.view = \u0412\u0438\u0434 -menu.file.view.resources = \u0420\u0435\u0441\u0443\u0440\u0441\u044b -menu.file.view.hex = Hex \u043e\u0431\u0440\u0430\u0437 - -node.header = \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a - -header.signature = \u041f\u043e\u0434\u043f\u0438\u0441\u044c: -header.compression = \u0421\u0436\u0430\u0442\u0438\u0435: -header.compression.lzma = LZMA -header.compression.zlib = ZLIB -header.compression.none = \u0411\u0435\u0437 \u0441\u0436\u0430\u0442\u0438\u044f -header.version = \u0412\u0435\u0440\u0441\u0438\u044f SWF: -header.gfx = GFX: -header.filesize = \u0420\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430: -header.framerate = \u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432: -header.framecount = \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u0434\u0440\u043e\u0432: -header.displayrect = \u041e\u0431\u043b\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430: -header.displayrect.value.twips = %xmin%,%ymin% => %xmax%,%ymax% \u0442\u0432\u0438\u043f\u043e\u0432 -header.displayrect.value.pixels = %xmin%,%ymin% => %xmax%,%ymax% \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 - -#after version 2.1.2 -contextmenu.saveToFile = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0444\u0430\u0439\u043b -contextmenu.parseActions = \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 -contextmenu.parseABC = \u041f\u0430\u0440\u0441\u0438\u043d\u0433 ABC -contextmenu.parseInstructions = \u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 AVM2 - -#after version 2.1.3 -menu.deobfuscation = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f AS1/2 -menu.file.deobfuscation.old = \u0421\u0442\u0430\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 -menu.file.deobfuscation.new = \u041d\u043e\u0432\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 - -#after version 2.1.4 -contextmenu.openswfinside = \u041e\u0442\u043a\u0440\u044b\u0442\u044c SWF \u0432\u043d\u0443\u0442\u0440\u0438 \u044d\u0442\u043e\u0433\u043e \u0442\u044d\u0433\u0430 -binarydata.swfInside = \u041f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c binary data \u0442\u044d\u0433\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f SWF. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0442\u0443\u0442 \u0434\u043b\u044f \u0435\u0433\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0434\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438. - -#after version 3.0.0 -button.zoomin.hint = \u041f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u044c -button.zoomout.hint = \u041e\u0442\u0434\u0430\u043b\u0438\u0442\u044c -button.zoomfit.hint = \u0412\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043e\u043a\u043d\u043e -button.zoomnone.hint = \u041c\u0430\u0441\u0448\u0442\u0430\u0431 1:1 -button.snapshot.hint = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u043d\u0438\u043c\u043e\u043a \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 - -editorTruncateWarning = \u0412 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u0442\u0435\u043a\u0441\u0442 \u043e\u0442\u0441\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 \u043d\u043e\u043c\u0435\u0440 %chars%. - -#Font name which is presented in the SWF Font tag -font.name.intag = \u0418\u043c\u044f \u0448\u0440\u0438\u0444\u0442\u0430 \u0432 \u0442\u044d\u0433\u0435: - -menu.debugger = \u041e\u0442\u043b\u0430\u0434\u0447\u0438\u043a -menu.debugger.switch = \u041e\u0442\u043b\u0430\u0434\u0447\u0438\u043a -menu.debugger.replacetrace = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u044b trace -menu.debugger.showlog = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u043e\u0433 - -message.debugger = \u041e\u0442\u043b\u0430\u0434\u0447\u0438\u043a SWF \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u043e\u043a\u043d\u043e \u043b\u043e\u0433\u0430, \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439.\r\n\u041e\u043d \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043a\u0430\u043a \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430, \u0442\u043e\u0447\u043a\u0438 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0438 \u0442.\u0434. - -contextmenu.addTag = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u044d\u0433 - -deobfuscation.comment.tryenable = \u0421\u043e\u0432\u0435\u0442: \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e" \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 -deobfuscation.comment.failed = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430, \u043d\u043e \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u041d\u0415 \u043e\u0431\u0444\u0443\u0441\u0446\u0438\u0440\u043e\u0432\u0430\u043d, \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u0435 "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e" \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432. - -#after version 4.0.2 -preview.nextframe = \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u0430\u0434\u0440 -preview.prevframe = \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u043a\u0430\u0434\u0440 -preview.gotoframe = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043a\u0430\u0434\u0440\u0443... - -preview.gotoframe.dialog.title = \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043a \u043a\u0430\u0434\u0440\u0443 -preview.gotoframe.dialog.message = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u043c\u0435\u0440 \u043a\u0430\u0434\u0440\u0430 (%min% - %max%) -preview.gotoframe.dialog.frame.error = \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043a\u0430\u0434\u0440\u0430. \u041e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 %min% \u0434\u043e %max%. - -error.text.invalid.continue = \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442: %text% \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0435 %line%. \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? - -#after version 4.0.5 -contextmenu.copyTag = \u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u044d\u0433 \u0432 -fit = fit -button.setAdvanceValues = \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f - -menu.tools.replace = \u0417\u0430\u043c\u0435\u043d\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 - -message.confirm.close = \u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044c {swfName}? -message.confirm.closeAll = \u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 SWF? - -contextmenu.exportJavaSource = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 Java -contextmenu.exportSwfXml = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SWF \u043a\u0430\u043a XML -contextmenu.importSwfXml = \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SWF XML - -filter.xml = XML - -#after version 4.1.0 -contextmenu.undo = \u041e\u0442\u043c\u0435\u043d\u0430 - -text.align.left = \u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e -text.align.right = \u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e -text.align.center = \u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443 -text.align.justify = \u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435 - -text.undo = \u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f - -menu.file.import.xml = \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SWF XML -menu.file.export.xml = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SWF XML - -#after version 4.1.1 -text.align.translatex.decrease = \u0423\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c TranslateX -text.align.translatex.increase = \u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c TranslateX -selectPreviousTag = \u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0442\u044d\u0433 -selectNextTag = \u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u044d\u0433 -button.ignoreAll = \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 -menu.file.import.symbolClass = \u041a\u043b\u0430\u0441\u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 +# Copyright (C) 2010-2015 JPEXS +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +menu.file = \u0424\u0430\u0439\u043b +menu.file.open = \u041e\u0442\u043a\u0440\u044b\u0442\u044c... +menu.file.save = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c +menu.file.saveas = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a... +menu.file.export.fla = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 FLA +menu.file.export.all = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0451 +menu.file.export.selection = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 +menu.file.exit = \u0412\u044b\u0439\u0442\u0438 + +menu.tools = \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b +menu.tools.searchas = \u041f\u043e\u0438\u0441\u043a \u043f\u043e \u0432\u0441\u0435\u043c\u0443 ActionScript... +menu.tools.proxy = \u041f\u0440\u043e\u043a\u0441\u0438 +menu.tools.deobfuscation = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f +menu.tools.deobfuscation.pcode = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f P-code... +menu.tools.deobfuscation.globalrename = \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 +menu.tools.deobfuscation.renameinvalid = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b +menu.tools.gotoDocumentClass = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443 + +menu.settings = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 +menu.settings.autodeobfuscation = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f +menu.settings.internalflashviewer = \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u044c Flash +menu.settings.parallelspeedup = \u041c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c (\u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b) +menu.settings.disabledecompilation = \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0438\u0437\u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c) +menu.settings.addtocontextmenu = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c FFDec \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435 \u043c\u0435\u043d\u044e SWF \u0444\u0430\u0439\u043b\u043e\u0432 +menu.settings.language = \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u044f\u0437\u044b\u043a +menu.settings.cacheOnDisk = \u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0434\u0438\u0441\u043a +menu.settings.gotoMainClassOnStartup = \u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 + +menu.help = \u041f\u043e\u043c\u043e\u0449\u044c +menu.help.checkupdates = \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f... +menu.help.helpus = \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043d\u0430\u0441! +menu.help.homepage = \u0414\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 +menu.help.about = \u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435... + +contextmenu.remove = \u0423\u0434\u0430\u043b\u0438\u0442\u044c + +button.save = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c +button.edit = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c +button.cancel = \u041e\u0442\u043c\u0435\u043d\u0430 +button.replace = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c... + +notavailonthisplatform = \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f Windows). + +swfpreview = \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 SWF +swfpreview.internal = \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 SWF (\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u044c) + +parameters = \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b + +rename.enternew = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u0438\u043c\u044f: + +rename.finished.identifier = \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d. +rename.finished.multiname = %count% multiname \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043e. + +node.texts = \u0442\u0435\u043a\u0441\u0442\u044b +node.images = \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f +node.movies = \u0432\u0438\u0434\u0435\u043e +node.sounds = \u0437\u0432\u0443\u043a\u0438 +node.binaryData = \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 +node.fonts = \u0448\u0440\u0438\u0444\u0442\u044b +node.sprites = \u0441\u043f\u0440\u0430\u0439\u0442\u044b +node.shapes = \u0444\u043e\u0440\u043c\u044b +node.morphshapes = morphshapes +node.buttons = \u043a\u043d\u043e\u043f\u043a\u0438 +node.frames = \u043a\u0430\u0434\u0440\u044b +node.scripts = \u0441\u043a\u0440\u0438\u043f\u0442\u044b + +message.warning = \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 +message.confirm.experimental = \u041f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0432\u0440\u0435\u0434\u0438\u0442\u044c SWF \u0444\u0430\u0439\u043b \u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0438\u043c.\r\n\u0418\u0421\u041f\u041e\u041b\u042c\u0417\u0423\u0419\u0422\u0415 \u041d\u0410 \u0421\u0412\u041e\u0419 \u0421\u0422\u0420\u0410\u0425 \u0418 \u0420\u0418\u0421\u041a! \u0412\u044b \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? +message.confirm.parallel = \u041c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0436\u0435\u0442 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0438 \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e, \u043d\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0430\u043c\u044f\u0442\u0438. +message.confirm.on = \u0412\u041a\u041b\u044e\u0447\u0438\u0442\u044c? +message.confirm.off = \u0412\u042b\u041a\u041b\u044e\u0447\u0438\u0442\u044c? +message.confirm = \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c + +message.confirm.autodeobfuscate = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0444\u0443\u0441\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434.\r\n\u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u0435\u0442 \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \"\u043c\u0451\u0440\u0442\u0432\u043e\u0433\u043e\" \u043a\u043e\u0434\u0430.\r\n\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e \u043b\u0443\u0447\u0448\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u043a\u043e\u0434 \u043d\u0435 \u043e\u0431\u0444\u0443\u0441\u0446\u0438\u0440\u043e\u0432\u0430\u043d. + +message.parallel = \u041c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c +message.trait.saved = Trait \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d + +message.constant.new.string = \u0421\u0442\u0440\u043e\u043a\u0430 (String) "%value%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c? +message.constant.new.string.title = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 (String) +message.constant.new.integer = \u0426\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Integer) "%value%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c? +message.constant.new.integer.title = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Integer) +message.constant.new.unsignedinteger = \u0411\u0435\u0437\u0437\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Unsigned integer) "%value%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c? +message.constant.new.unsignedinteger.title = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0435\u0437\u0437\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Unsigned integer) +message.constant.new.double = \u0414\u0440\u043e\u0431\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Double) "%value%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c? +message.constant.new.double.title = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e (Double) + +work.buffering = \u0411\u0443\u0444\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f +work.waitingfordissasembly = \u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0434\u0438\u0437\u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f +work.gettinghilights = \u041f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 +work.disassembling = \u0414\u0438\u0437\u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 +work.exporting = \u042d\u043a\u0441\u043f\u043e\u0440\u0442 +work.searching = \u041f\u043e\u0438\u0441\u043a +work.renaming = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 +work.exporting.fla = \u042d\u043a\u0441\u043f\u043e\u0440\u0442 FLA +work.renaming.identifiers = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 +work.deobfuscating = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f +work.decompiling = \u0414\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f +work.gettingvariables = \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 +work.reading.swf = \u0427\u0442\u0435\u043d\u0438\u0435 SWF +work.creatingwindow = \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u043a\u043d\u0430 +work.buildingscripttree = \u041f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0434\u0435\u0440\u0435\u0432\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 + +work.deobfuscating.complete = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430 + +message.search.notfound = \u0422\u0435\u043a\u0441\u0442 "%searchtext%" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d. +message.search.notfound.title = \u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e + +message.rename.notfound.multiname = \u041f\u043e\u0434 \u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c multiname +message.rename.notfound.identifier = \u041f\u043e\u0434 \u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 +message.rename.notfound.title = \u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e +message.rename.renamed = \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043e: %count% + +filter.images = \u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f (*.jpg,*.gif,*.png,*.bmp) +filter.fla = \u041f\u0440\u043e\u0435\u043a\u0442 %version% (*.fla) +filter.xfl = \u041d\u0435\u0441\u0436\u0430\u0442\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 %version% (*.xfl) +filter.swf = SWF \u0444\u0430\u0439\u043b\u044b (*.swf) + +error = \u041e\u0448\u0438\u0431\u043a\u0430 +error.image.invalid = \u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435. + +error.text.invalid = \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442: %text% \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 %line% +error.file.save = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0444\u0430\u0439\u043b +error.file.write = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0444\u0430\u0439\u043b +error.export = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 + +export.select.directory = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 +export.finishedin = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0437\u0430 %time% + +update.check.title = \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 +update.check.nonewversion = \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043d\u0435\u0442. + +message.helpus = \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\r\n%url%\r\n\u0434\u043b\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0435\u0439. +message.homepage = \u041f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443: \r\n%url% + +proxy = \u041f\u0440\u043e\u043a\u0441\u0438 +proxy.start = \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438 +proxy.stop = \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438 +proxy.show = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438 +exit = \u0412\u044b\u0439\u0442\u0438 + +panel.disassembled = P-\u043a\u043e\u0434 +panel.decompiled = ActionScript + +search.info = \u041f\u043e\u0438\u0441\u043a "%text%": +search.script = \u0421\u043a\u0440\u0438\u043f\u0442 + +constants = Constants +traits = Traits + +pleasewait = \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435 + +abc.detail.methodtrait = Method/Getter/Setter Trait +abc.detail.unsupported = - +abc.detail.slotconsttrait = Slot/Const Trait +abc.detail.traitname = \u0418\u043c\u044f: + +abc.detail.body.params.maxstack = \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0442\u0435\u043a\u0430: +abc.detail.body.params.localregcount = \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432: +abc.detail.body.params.minscope = \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438: +abc.detail.body.params.maxscope = \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438: +abc.detail.body.params.autofill = \u0410\u0432\u0442\u043e\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043a\u043e\u0434\u0430 (\u0413\u041b\u041e\u0411\u0410\u041b\u042c\u041d\u0410\u042f \u041d\u0410\u0421\u0422\u0420\u041e\u0419\u041a\u0410) +abc.detail.body.params.autofill.experimental = ...\u042d\u041a\u0421\u041f\u0415\u0420\u0418\u041c\u0415\u041d\u0422\u0410\u041b\u042c\u041d\u041e + +abc.detail.methodinfo.methodindex = \u0418\u043d\u0434\u0435\u043a\u0441 \u043c\u0435\u0442\u043e\u0434\u0430: +abc.detail.methodinfo.parameters = \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b: +abc.detail.methodinfo.returnvalue = \u0422\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f: + +error.methodinfo.params = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445 MethodInfo +error.methodinfo.returnvalue = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0442\u0438\u043f\u0435 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f MethodInfo + +abc.detail.methodinfo = MethodInfo +abc.detail.body.code = \u041a\u043e\u0434 MethodBody +abc.detail.body.params = \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b MethodBody + +abc.detail.slotconst.typevalue = \u0422\u0438\u043f \u0438 \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435: + +error.slotconst.typevalue = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0442\u0438\u043f\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f SlotConst + +message.autofill.failed = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432.\r\n\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. +info.selecttrait = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u043b\u0430\u0441\u0441 \u0438 \u043a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u043d\u0430 trait \u0432 ActionScript \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. + +button.viewgraph = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0413\u0440\u0430\u0444\u0430 +button.viewhex = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 Hex + +abc.traitslist.instanceinitializer = \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 +abc.traitslist.classinitializer = \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 + +action.edit.experimental = (\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e) + +message.action.saved = \u041a\u043e\u0434 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d + +error.action.save = %error% \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 %line% + +message.confirm.remove = \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 %item%\n \u0438 \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u043e\u0442 \u043d\u0435\u0433\u043e? + +#after version 1.6.5u1: + +button.ok = OK +button.cancel = \u041e\u0442\u043c\u0435\u043d\u0430 + +font.name = \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0448\u0440\u0438\u0444\u0442\u0430: +font.isbold = \u0416\u0438\u0440\u043d\u044b\u0439: +font.isitalic = \u041a\u0443\u0440\u0441\u0438\u0432: +font.ascent = \u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0432\u044b\u043d\u043e\u0441: +font.descent = \u041d\u0438\u0436\u043d\u0438\u0439 \u0432\u044b\u043d\u043e\u0441: +font.leading = \u0418\u043d\u0442\u0435\u0440\u043b\u0438\u043d\u044c\u044f\u0436: +font.characters = \u0421\u0438\u043c\u0432\u043e\u043b\u044b: +font.characters.add = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0438\u043c\u0432\u043e\u043b\u044b: +value.unknown = ? + +yes = \u0434\u0430 +no = \u043d\u0435\u0442 + +errors.present = \u0412 \u043b\u043e\u0433\u0435 \u0435\u0441\u0442\u044c \u041e\u0428\u0418\u0411\u041a\u0418. \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. +errors.none = \u0412 \u043b\u043e\u0433\u0435 \u043d\u0435\u0442 \u043e\u0448\u0438\u0431\u043e\u043a. + +#after version 1.6.6: + +dialog.message.title = \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 +dialog.select.title = \u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 + +button.yes = \u0414\u0430 +button.no = \u041d\u0435\u0442 + +FileChooser.openButtonText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c +FileChooser.openButtonToolTipText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c +FileChooser.lookInLabelText = \u0418\u0441\u043a\u0430\u0442\u044c \u0432: +FileChooser.acceptAllFileFilterText = \u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b +FileChooser.filesOfTypeLabelText = \u0422\u0438\u043f \u0444\u0430\u0439\u043b\u043e\u0432: +FileChooser.fileNameLabelText = \u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430: +FileChooser.listViewButtonToolTipText = \u0421\u043f\u0438\u0441\u043e\u043a +FileChooser.listViewButtonAccessibleName = \u0421\u043f\u0438\u0441\u043e\u043a +FileChooser.detailsViewButtonToolTipText = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 +FileChooser.detailsViewButtonAccessibleName = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 +FileChooser.upFolderToolTipText = \u0412\u0432\u0435\u0440\u0445 +FileChooser.upFolderAccessibleName = \u0412\u0432\u0435\u0440\u0445 +FileChooser.homeFolderToolTipText = \u0414\u043e\u043c\u043e\u0439 +FileChooser.homeFolderAccessibleName = \u0414\u043e\u043c\u043e\u0439 +FileChooser.fileNameHeaderText = \u0418\u043c\u044f +FileChooser.fileSizeHeaderText = \u0420\u0430\u0437\u043c\u0435\u0440 +FileChooser.fileTypeHeaderText = \u0422\u0438\u043f +FileChooser.fileDateHeaderText = \u0414\u0430\u0442\u0430 +FileChooser.fileAttrHeaderText = \u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b +FileChooser.openDialogTitleText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c +FileChooser.directoryDescriptionText = \u041f\u0430\u043f\u043a\u0430 +FileChooser.directoryOpenButtonText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c +FileChooser.directoryOpenButtonToolTipText = \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 +FileChooser.fileDescriptionText = \u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b +FileChooser.helpButtonText = \u041f\u043e\u043c\u043e\u0449\u044c +FileChooser.helpButtonToolTipText = \u041f\u043e\u043c\u043e\u0449\u044c \u043f\u043e \u0434\u0438\u0430\u043b\u043e\u0433\u0443 \u0432\u044b\u0431\u043e\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 +FileChooser.newFolderAccessibleName = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 +FileChooser.newFolderErrorText = \u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 +FileChooser.newFolderToolTipText = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443 +FileChooser.other.newFolder = \u041d\u043e\u0432\u0430\u044f\u041f\u0430\u043f\u043a\u0430 +FileChooser.other.newFolder.subsequent = \u041d\u043e\u0432\u0430\u044f\u041f\u0430\u043f\u043a\u0430.{0} +FileChooser.win32.newFolder = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 +FileChooser.win32.newFolder.subsequent = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 ({0}) +FileChooser.saveButtonText = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c +FileChooser.saveButtonToolTipText = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b +FileChooser.saveDialogTitleText = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c +FileChooser.saveInLabelText = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432: +FileChooser.updateButtonText = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c +FileChooser.updateButtonToolTipText = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0430\u043f\u043a\u0438 + +#after version 1.6.6u2: + +FileChooser.detailsViewActionLabel.textAndMnemonic = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 +FileChooser.detailsViewButtonToolTip.textAndMnemonic = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 +FileChooser.fileAttrHeader.textAndMnemonic = \u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b +FileChooser.fileDateHeader.textAndMnemonic = \u0418\u0437\u043c\u0435\u043d\u0435\u043d +FileChooser.fileNameHeader.textAndMnemonic = \u0418\u043c\u044f +FileChooser.fileNameLabel.textAndMnemonic = \u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430: +FileChooser.fileSizeHeader.textAndMnemonic = \u0420\u0430\u0437\u043c\u0435\u0440 +FileChooser.fileTypeHeader.textAndMnemonic = \u0422\u0438\u043f +FileChooser.filesOfTypeLabel.textAndMnemonic = \u0424\u0430\u0439\u043b\u044b \u0442\u0438\u043f\u0430: +FileChooser.folderNameLabel.textAndMnemonic = \u0418\u043c\u044f \u043f\u0430\u043f\u043a\u0438: +FileChooser.homeFolderToolTip.textAndMnemonic = \u0414\u043e\u043c\u043e\u0439 +FileChooser.listViewActionLabel.textAndMnemonic = \u0421\u043f\u0438\u0441\u043e\u043a +FileChooser.listViewButtonToolTip.textAndMnemonic = \u0421\u043f\u0438\u0441\u043e\u043a +FileChooser.lookInLabel.textAndMnemonic = \u0418\u0441\u043a\u0430\u0442\u044c \u0432: +FileChooser.newFolderActionLabel.textAndMnemonic = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 +FileChooser.newFolderToolTip.textAndMnemonic = \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443 +FileChooser.refreshActionLabel.textAndMnemonic = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c +FileChooser.saveInLabel.textAndMnemonic = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432: +FileChooser.upFolderToolTip.textAndMnemonic = \u0412\u0432\u0435\u0440\u0445 +FileChooser.viewMenuButtonAccessibleName = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u041c\u0435\u043d\u044e +FileChooser.viewMenuButtonToolTipText = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u041c\u0435\u043d\u044e +FileChooser.viewMenuLabel.textAndMnemonic = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 +FileChooser.newFolderActionLabelText = \u041d\u043e\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 +FileChooser.listViewActionLabelText = \u0421\u043f\u0438\u0441\u043e\u043a +FileChooser.detailsViewActionLabelText = \u0422\u0430\u0431\u043b\u0438\u0446\u0430 +FileChooser.refreshActionLabelText = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c +FileChooser.sortMenuLabelText = \u0423\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u043a\u0438 +FileChooser.viewMenuLabelText = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 +FileChooser.fileSizeKiloBytes = {0} \u041a\u0411 +FileChooser.fileSizeMegaBytes = {0} \u041c\u0411 +FileChooser.fileSizeGigaBytes = {0} \u0413\u0411 +FileChooser.folderNameLabelText = \u0418\u043c\u044f \u043f\u0430\u043f\u043a\u0438: + +error.occured = \u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430: %error% +button.abort = \u041f\u0440\u0435\u0440\u0432\u0430\u0442\u044c +button.retry = \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c +button.ignore = \u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c + +font.source = \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u0448\u0440\u0438\u0444\u0442\u0430: + +#after version 1.6.7: + +menu.export = \u042d\u043a\u0441\u043f\u043e\u0440\u0442 +menu.general = \u041e\u0431\u0449\u0438\u0435 +menu.language = \u042f\u0437\u044b\u043a + +startup.welcometo = \u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 +startup.selectopen = \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u043e\u043a "\u041e\u0442\u043a\u0440\u044b\u0442\u044c" \u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435 SWF \u0444\u0430\u0439\u043b \u0432 \u044d\u0442\u043e \u043e\u043a\u043d\u043e. + +error.font.nocharacter = \u0421\u0438\u043c\u0432\u043e\u043b "%char%" \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c \u0448\u0440\u0438\u0444\u0442\u0435. + +warning.initializers = \u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430\u0445.\n\u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0445 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0434\u0435\u0441\u044c, \u043d\u043e \u0438 \u0442\u0430\u043c! + +#after version 1.7.0u1: + +menu.tools.searchMemory = \u0418\u0441\u043a\u0430\u0442\u044c SWF \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 +menu.file.reload = \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c +message.confirm.reload = \u042d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u043d\u0435\u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043d\u043e\u0432\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 SWF \u0444\u0430\u0439\u043b.\n \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? + +dialog.selectbkcolor.title = \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u0444\u043e\u043d\u0430 \u0434\u043b\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 SWF +button.selectbkcolor.hint = \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u0444\u043e\u043d\u0430 + +ColorChooser.okText = \u041e\u041a +ColorChooser.cancelText = \u041e\u0442\u043c\u0435\u043d\u0430 +ColorChooser.resetText = \u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c +ColorChooser.previewText = \u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 +ColorChooser.swatchesNameText = \u041e\u0431\u0440\u0430\u0437\u0446\u044b +ColorChooser.swatchesRecentText = \u041d\u0435\u0434\u0430\u0432\u043d\u0435\u0435: +ColorChooser.sampleText = \u041f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0434\u043f\u0438\u0441\u0438 \u041f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0434\u043f\u0438\u0441\u0438 + +#after version 1.7.1: + +preview.play = \u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 +preview.pause = \u041f\u0430\u0443\u0437\u0430 +preview.stop = \u0421\u0442\u043e\u043f + +message.confirm.removemultiple = \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435: %count%\n \u0438 \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u043e\u0442 \u043d\u0438\u0445? + +menu.tools.searchCache = \u041f\u043e\u0438\u0441\u043a \u0432 \u043a\u044d\u0448\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 + +#after version 1.7.2u2 + +error.trait.exists = Trait \u0441 \u0438\u043c\u0435\u043d\u0435\u043c "%name%" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. +button.addtrait = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c trait +button.font.embed = \u0412\u0441\u0442\u0440\u043e\u0438\u0442\u044c... +button.yes.all = \u0414\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 +button.no.all = \u041d\u0435\u0442 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 +message.font.add.exists = \u0421\u0438\u043c\u0432\u043e\u043b %char% \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u044d\u0433\u0435 \u0448\u0440\u0438\u0444\u0442\u0430.\n\u0416\u0435\u043b\u0430\u0435\u0442\u0435 \u043b\u0438 \u0412\u044b \u0435\u0433\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c? + +filter.gfx = GFx \u0444\u0430\u0439\u043b\u044b ScaleForm (*.gfx) +filter.supported = \u0412\u0441\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b +work.canceled = \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u043e +work.restoringControlFlow = \u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 +menu.advancedsettings.advancedsettings = \u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 +menu.recentFiles = \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u044b + +#after version 1.7.4 +work.restoringControlFlow.complete = \u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d +message.confirm.recentFileNotFound = \u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d. \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0435\u0433\u043e \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432? +contextmenu.closeSwf = \u0417\u0430\u043a\u0440\u044b\u0442\u044c SWF +menu.settings.autoRenameIdentifiers = \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b +menu.file.saveasexe = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a Exe... +filter.exe = \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (*.exe) + +#after version 1.8.0 +font.updateTexts = \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0430\u0434\u043f\u0438\u0441\u0438 + +#after version 1.8.0u1 +menu.file.close = \u0417\u0430\u043a\u0440\u044b\u0442\u044c +menu.file.closeAll = \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 +menu.tools.otherTools = \u0414\u0440\u0443\u0433\u043e\u0435 +menu.tools.otherTools.clearRecentFiles = \u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 +fontName.name = \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0448\u0440\u0438\u0444\u0442\u0430: +fontName.copyright = \u0410\u0432\u0442\u043e\u0440\u0441\u043a\u043e\u0435 \u043f\u0440\u0430\u0432\u043e: +button.preview = \u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 +button.reset = \u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c +errors.info = \u0412 \u043b\u043e\u0433\u0435 \u0435\u0441\u0442\u044c \u0432\u0430\u0436\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. +errors.warning = \u0412 \u043b\u043e\u0433\u0435 \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f! \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. + +decompilationError = \u041e\u0448\u0438\u0431\u043a\u0430 \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 + +disassemblingProgress.toString = \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u043e\u043a +disassemblingProgress.reading = \u0427\u0442\u0435\u043d\u0438\u0435 +disassemblingProgress.deobfuscating = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f + +contextmenu.moveTag = \u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0442\u044d\u0433 + +filter.swc = SWC \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 (*.swc) +filter.zip = ZIP \u0430\u0440\u0445\u0438\u0432\u044b (*.zip) +filter.binary = \u0411\u0438\u043d\u0430\u0440\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a - \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b (*.*) + +open.error = \u041e\u0448\u0438\u0431\u043a\u0430 +open.error.fileNotFound = \u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d +open.error.cannotOpen = \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0444\u0430\u0439\u043b + +node.others = \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 + +#after version 1.8.1 +menu.tools.search = \u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430 + +#after version 1.8.1u1 +menu.tools.timeline = Timeline + +dialog.selectcolor.title = \u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u0430 +button.selectcolor.hint = \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0446\u0432\u0435\u0442\u0430 + +#default item name, will be used in following sentences +generictag.array.item = \u044d\u043b\u0435\u043c\u0435\u043d\u0442 +generictag.array.insertbeginning = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c %item% \u0432 \u043d\u0430\u0447\u0430\u043b\u043e +generictag.array.insertbefore = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c %item% \u043f\u0435\u0440\u0435\u0434 +generictag.array.remove = \u0423\u0434\u0430\u043b\u0438\u0442\u044c %item% +generictag.array.insertafter = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c %item% \u043f\u043e\u0441\u043b\u0435 +generictag.array.insertend = \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c %item% \u0432 \u043a\u043e\u043d\u0435\u0446 + +#after version 2.0.0 +contextmenu.expandAll = \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u0441\u0435 + +filter.sounds = \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0437\u0432\u0443\u043a\u043e\u0432\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b (*.wav,*.mp3) +filter.sounds.wav = Wave \u0444\u043e\u0440\u043c\u0430\u0442 (*.wav) +filter.sounds.mp3 = MP3 \u0441\u0436\u0430\u0442\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 (*.mp3) + +error.sound.invalid = \u041d\u0435 \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 \u0437\u0432\u0443\u043a. + +button.prev = \u041d\u0430\u0437\u0430\u0434 +button.next = \u0414\u0430\u043b\u0435\u0435 + +#after version 2.1.0 +message.action.playerglobal.title = \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 PlayerGlobal +message.action.playerglobal.needed = \u0414\u043b\u044f \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f ActionScript 3 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 "PlayerGlobal.swc" \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Adobe.\r\n%adobehomepage%\r\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 OK, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044e. +message.action.playerglobal.place = \u0421\u043a\u0430\u0447\u0430\u0439\u0442\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 PlayerGlobal(.swc), \u0438 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u0435 \u0435\u0435 \u0432 \u043f\u0430\u043f\u043a\u0435\r\n%libpath%\r\n\u041d\u0430\u0436\u043c\u0438\u0442\u0435 OK \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f. + +message.confirm.experimental.function = \u042d\u0442\u043e \u042d\u041a\u0421\u041f\u0415\u0420\u0418\u041c\u0415\u041d\u0422\u0410\u041b\u042c\u041d\u0410\u042f \u0444\u0443\u043d\u043a\u0446\u0438\u044f. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0432\u0430\u043c \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0434\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c \u0438 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 swf \u0444\u0430\u0439\u043b \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e. +message.confirm.donotshowagain = \u041d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 + +menu.import = \u0418\u043d\u043f\u043e\u0440\u0442 +menu.file.import.text = \u0418\u043c\u043f\u043e\u0440\u0442 \u0442\u0435\u043a\u0441\u0442\u0430 +import.select.directory = \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 +error.text.import = \u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 \u0442\u0435\u043a\u0441\u0442\u0430. \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? + +#after version 2.1.1 +contextmenu.removeWithDependencies = \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 + +abc.action.find-usages = \u041d\u0430\u0439\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f +abc.action.find-declaration = \u041d\u0430\u0439\u0442\u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 + +contextmenu.rawEdit = \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0430\u0439\u0442\u044b +contextmenu.jumpToCharacter = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u0438\u043c\u0432\u043e\u043b\u0443 + +menu.settings.dumpView = \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u043e\u0431\u0440\u0430\u0437\u0430 + +menu.view = \u0412\u0438\u0434 +menu.file.view.resources = \u0420\u0435\u0441\u0443\u0440\u0441\u044b +menu.file.view.hex = Hex \u043e\u0431\u0440\u0430\u0437 + +node.header = \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a + +header.signature = \u041f\u043e\u0434\u043f\u0438\u0441\u044c: +header.compression = \u0421\u0436\u0430\u0442\u0438\u0435: +header.compression.lzma = LZMA +header.compression.zlib = ZLIB +header.compression.none = \u0411\u0435\u0437 \u0441\u0436\u0430\u0442\u0438\u044f +header.version = \u0412\u0435\u0440\u0441\u0438\u044f SWF: +header.gfx = GFX: +header.filesize = \u0420\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430: +header.framerate = \u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432: +header.framecount = \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u0434\u0440\u043e\u0432: +header.displayrect = \u041e\u0431\u043b\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430: +header.displayrect.value.twips = %xmin%,%ymin% => %xmax%,%ymax% \u0442\u0432\u0438\u043f\u043e\u0432 +header.displayrect.value.pixels = %xmin%,%ymin% => %xmax%,%ymax% \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 + +#after version 2.1.2 +contextmenu.saveToFile = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0444\u0430\u0439\u043b +contextmenu.parseActions = \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 +contextmenu.parseABC = \u041f\u0430\u0440\u0441\u0438\u043d\u0433 ABC +contextmenu.parseInstructions = \u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 AVM2 + +#after version 2.1.3 +menu.deobfuscation = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f +menu.file.deobfuscation.old = \u0421\u0442\u0430\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 +menu.file.deobfuscation.new = \u041d\u043e\u0432\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 + +#after version 2.1.4 +contextmenu.openswfinside = \u041e\u0442\u043a\u0440\u044b\u0442\u044c SWF \u0432\u043d\u0443\u0442\u0440\u0438 \u044d\u0442\u043e\u0433\u043e \u0442\u044d\u0433\u0430 +binarydata.swfInside = \u041f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c binary data \u0442\u044d\u0433\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f SWF. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0442\u0443\u0442 \u0434\u043b\u044f \u0435\u0433\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0434\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438. + +#after version 3.0.0 +button.zoomin.hint = \u041f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u044c +button.zoomout.hint = \u041e\u0442\u0434\u0430\u043b\u0438\u0442\u044c +button.zoomfit.hint = \u0412\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043e\u043a\u043d\u043e +button.zoomnone.hint = \u041c\u0430\u0441\u0448\u0442\u0430\u0431 1:1 +button.snapshot.hint = \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u043d\u0438\u043c\u043e\u043a \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430 + +editorTruncateWarning = \u0412 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u0442\u0435\u043a\u0441\u0442 \u043e\u0442\u0441\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 \u043d\u043e\u043c\u0435\u0440 %chars%. + +#Font name which is presented in the SWF Font tag +font.name.intag = \u0418\u043c\u044f \u0448\u0440\u0438\u0444\u0442\u0430 \u0432 \u0442\u044d\u0433\u0435: + +menu.debugger = \u041e\u0442\u043b\u0430\u0434\u0447\u0438\u043a +menu.debugger.switch = \u041e\u0442\u043b\u0430\u0434\u0447\u0438\u043a +menu.debugger.replacetrace = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u044b trace +menu.debugger.showlog = \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u043e\u0433 + +message.debugger = \u041e\u0442\u043b\u0430\u0434\u0447\u0438\u043a SWF \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u043e\u043a\u043d\u043e \u043b\u043e\u0433\u0430, \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439.\r\n\u041e\u043d \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043a\u0430\u043a \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430, \u0442\u043e\u0447\u043a\u0438 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0438 \u0442.\u0434. + +contextmenu.addTag = \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u044d\u0433 + +deobfuscation.comment.tryenable = \u0421\u043e\u0432\u0435\u0442: \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e" \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 +deobfuscation.comment.failed = \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430, \u043d\u043e \u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u041d\u0415 \u043e\u0431\u0444\u0443\u0441\u0446\u0438\u0440\u043e\u0432\u0430\u043d, \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u0435 "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e" \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432. + +#after version 4.0.2 +preview.nextframe = \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u0430\u0434\u0440 +preview.prevframe = \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u043a\u0430\u0434\u0440 +preview.gotoframe = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043a\u0430\u0434\u0440\u0443... + +preview.gotoframe.dialog.title = \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043a \u043a\u0430\u0434\u0440\u0443 +preview.gotoframe.dialog.message = \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u043c\u0435\u0440 \u043a\u0430\u0434\u0440\u0430 (%min% - %max%) +preview.gotoframe.dialog.frame.error = \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043a\u0430\u0434\u0440\u0430. \u041e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 %min% \u0434\u043e %max%. + +error.text.invalid.continue = \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442: %text% \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0435 %line%. \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c? + +#after version 4.0.5 +contextmenu.copyTag = \u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u044d\u0433 \u0432 +fit = fit +button.setAdvanceValues = \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f + +menu.tools.replace = \u0417\u0430\u043c\u0435\u043d\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 + +message.confirm.close = \u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044c {swfName}? +message.confirm.closeAll = \u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 SWF? + +contextmenu.exportJavaSource = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 Java +contextmenu.exportSwfXml = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SWF \u043a\u0430\u043a XML +contextmenu.importSwfXml = \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SWF XML + +filter.xml = XML + +#after version 4.1.0 +contextmenu.undo = \u041e\u0442\u043c\u0435\u043d\u0430 + +text.align.left = \u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e +text.align.right = \u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e +text.align.center = \u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443 +text.align.justify = \u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435 + +text.undo = \u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f + +menu.file.import.xml = \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SWF XML +menu.file.export.xml = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SWF XML + +#after version 4.1.1 +text.align.translatex.decrease = \u0423\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c TranslateX +text.align.translatex.increase = \u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c TranslateX +selectPreviousTag = \u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0442\u044d\u0433 +selectNextTag = \u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u044d\u0433 +button.ignoreAll = \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 +menu.file.import.symbolClass = \u041a\u043b\u0430\u0441\u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_sv.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_sv.properties index df9083949..cfaa65488 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_sv.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_sv.properties @@ -1,616 +1,616 @@ -# Copyright (C) 2010-2015 JPEXS -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -menu.file = Fil -menu.file.open = \u00d6ppna... -menu.file.save = Spara -menu.file.saveas = Spara som... -menu.file.export.fla = Exportera till FLA -menu.file.export.all = Exportera alla delar -menu.file.export.selection = Exportera markering -menu.file.exit = St\u00e4ng - -menu.tools = Verktyg -menu.tools.searchas = S\u00f6k igenom alla ActionSkript... -menu.tools.proxy = Proxy -menu.tools.deobfuscation = Avl\u00e4gsna obfuskering -menu.tools.deobfuscation.pcode = Avl\u00e4gsna obfuskerad Bytekod... -menu.tools.deobfuscation.globalrename = Byt namn p\u00e5 global identifierare -menu.tools.deobfuscation.renameinvalid = Byt namn p\u00e5 felaktiga identifierare -menu.tools.gotoDocumentClass = G\u00e5 till dokumentklass - -menu.settings = Inst\u00e4llningar -menu.settings.autodeobfuscation = Automatiskt avl\u00e4gsning av obfuskering -menu.settings.internalflashviewer = Anv\u00e4nd egen Flash-spelare -menu.settings.parallelspeedup = Parallell uppsnabbning -menu.settings.disabledecompilation = Inaktivera dekompilering (Demontera endast) -menu.settings.addtocontextmenu = L\u00e4gg till FFDec till SWF-filernas snabbmeny -menu.settings.language = Byt spr\u00e5k -menu.settings.cacheOnDisk = Anv\u00e4nd cachelagring p\u00e5 h\u00e5rddisken -menu.settings.gotoMainClassOnStartup = Markera dokumentklass vid uppstart - -menu.help = Hj\u00e4lp -menu.help.checkupdates = Leta efter uppdateringar... -menu.help.helpus = Hj\u00e4lp oss! -menu.help.homepage = Bes\u00f6k hemsidan -menu.help.about = Om... - -contextmenu.remove = Ta bort - -button.save = Spara -button.edit = \u00c4ndra -button.cancel = \u00c5ngra -button.replace = Ers\u00e4tt... - -notavailonthisplatform = F\u00f6rhandsgranskning av detta objekt \u00e4r inte tillg\u00e4nglig p\u00e5 denna plattform. (Windows bara) - -swfpreview = SWF f\u00f6rhandsvisning -swfpreview.internal = SWF f\u00f6rhandsvisning (Intern f\u00f6rhandsvisning) - -parameters = Parametrar - -rename.enternew = Ange det nya namnet: - -rename.finished.identifier = Identifierare omd\u00f6pt. -rename.finished.multiname = %count% multiname har blivit omd\u00f6pt(a). - -node.texts = texter -node.images = bilder -node.movies = filmer -node.sounds = ljud -node.binaryData = bin\u00e4rData -node.fonts = teckensnitt -node.sprites = sprites -node.shapes = former -node.morphshapes = morphform -node.buttons = knappar -node.frames = ramar -node.scripts = skript - -message.warning = Varning -message.confirm.experimental = F\u00f6ljande tillv\u00e4gag\u00e5ngss\u00e4tt kan skada SWF-filen som kan d\u00e4refter bli ospelbar.\r\nANV\u00c4ND DEN P\u00c5 DIN EGEN RISK. Vill du forts\u00e4tta? -message.confirm.parallel = Parallellitet kan snabba upp laddning och dekompilering, men anv\u00e4nda mera minne. -message.confirm.on = Vill du aktivera detta? -message.confirm.off = Vill du avaktivera detta? -message.confirm = Bekr\u00e4fta - -message.confirm.autodeobfuscate = Automatiskt avl\u00e4gsning av obfuskering \u00e4r ett s\u00e4tt till att dekompilera obfuskerad kod.\r\nAvl\u00e4gsna obfuskerad kod leder till sl\u00f6are dekompilering och n\u00e5gon d\u00f6d kod kan bli borttagen..\r\nOm koden inte \u00e4r obfuskerad, s\u00e5 \u00e4r det b\u00e4ttre att st\u00e4nga av automatisk borttagning av obfuskering. - -message.parallel = parallellitet -message.trait.saved = Egenskap har sparats - -message.constant.new.string = Str\u00e4ng "%value%" finns inte i konstant tabellen. Vill du l\u00e4gga till det? -message.constant.new.string.title = L\u00e4gg till Str\u00e4ng -message.constant.new.integer = Heltal v\u00e4rde "%value%" finns inte i konstant tabellen. Vill du l\u00e4gga till det? -message.constant.new.integer.title = L\u00e4gg till Heltal -message.constant.new.unsignedinteger = Osignerat heltal v\u00e4rde "%value%" finns inte i konstant tabellen. Vill du l\u00e4gga till det? -message.constant.new.unsignedinteger.title = L\u00e4gg till Osignerat heltal -message.constant.new.double = Dubbelt v\u00e4rde "%value%" finns inte i konstant tabellen. Vill du l\u00e4gga till det? -message.constant.new.double.title = L\u00e4gg till Dubbel - -work.buffering = Buffrar -work.waitingfordissasembly = V\u00e4ntar p\u00e5 demontering -work.gettinghilights = Getting hilights -work.disassembling = Demonterar -work.exporting = Exporterar -work.searching = S\u00f6ker -work.renaming = \u00c4ndrar namn -work.exporting.fla = Exporterar FLA -work.renaming.identifiers = \u00c4ndrar namn p\u00e5 identifierare -work.deobfuscating = Avl\u00e4gsning utav obfuskering -work.decompiling = Dekompilering -work.gettingvariables = Tar variablar -work.reading.swf = L\u00e4ser SWF -work.creatingwindow = Skapar f\u00f6nster -work.buildingscripttree = Bygger skript tr\u00e4 - -work.deobfuscating.complete = Avl\u00e4gsning utav obfuskering \u00e4r nu f\u00e4rdig - -message.search.notfound = Str\u00e4ng "%searchtext%" hittades inte. -message.search.notfound.title = Hittades inte - -message.rename.notfound.multiname = Ingen multiname hittades under mark\u00f6ren -message.rename.notfound.identifier = ingen identifiering hittades under mark\u00f6ren -message.rename.notfound.title = Hittades inte -message.rename.renamed = Identifierare som har \u00e4ndrat namn: %count% - -filter.images = Bilder (*.jpg,*.gif,*.png,*.bmp) -filter.fla = %version% Dokument (*.fla) -filter.xfl = %version% Okomprimerat Dokument (*.xfl) -filter.swf = SWF filer (*.swf) - -error = Fel -error.image.invalid = Ogiltig bild. - -error.text.invalid = Ogiltig text: %text% p\u00e5 rad %line% -error.file.save = Kan inte spara filen -error.file.write = Kan inte skriva till filen -error.export = Fel under loppet av exporteringen - -export.select.directory = V\u00e4lj s\u00f6kv\u00e4g till katalog att exportera -export.finishedin = Exporterades i %time% - -update.check.title = Uppdaterings koll -update.check.nonewversion = Ingen ny version finns tillg\u00e4nglig. - -message.helpus = V\u00e4nligen bes\u00f6k\r\n%url%\r\nf\u00f6r mer detaljer. -message.homepage = Bes\u00f6k hemsidan: \r\n%url% - -proxy = Proxy -proxy.start = Starta proxy -proxy.stop = Stoppa proxy -proxy.show = Visa proxy -exit = St\u00e4ng - -panel.disassembled = P-code k\u00e4llkod -panel.decompiled = ActionSkript k\u00e4llkod - -search.info = S\u00f6k efter "%text%" : -search.script = Skript - -constants = Konstanter -traits = Egenskaper - -pleasewait = V\u00e4nligen v\u00e4nta - -abc.detail.methodtrait = Metod/F\u00e5ngare/Egenskap s\u00e4ttare -abc.detail.unsupported = - -abc.detail.slotconsttrait = Slot/Const Egenskap -abc.detail.traitname = Namn: - -abc.detail.body.params.maxstack = Maximal stapling: -abc.detail.body.params.localregcount = Lokala register r\u00e4knade: -abc.detail.body.params.minscope = Minsta omfattnings djup: -abc.detail.body.params.maxscope = Maximal omfattnings djup: -abc.detail.body.params.autofill = Automatisk utfyllnad n\u00e4r koden sparas (GLOBAL INST\u00c4LLNING) -abc.detail.body.params.autofill.experimental = ...EXPERIMENTELL - -abc.detail.methodinfo.methodindex = Metod register: -abc.detail.methodinfo.parameters = Parametrar: -abc.detail.methodinfo.returnvalue = \u00c5terl\u00e4mna v\u00e4rde: - -error.methodinfo.params = MetodInfo Parameter fel -error.methodinfo.returnvalue = MetodInfo \u00e5terl\u00e4mmnings typ Fel - -abc.detail.methodinfo = MetodInfo -abc.detail.body.code = MetodInfo Kod -abc.detail.body.params = MetodKropp parametrar - -abc.detail.slotconst.typevalue = Typ och V\u00e4rde: - -error.slotconst.typevalue = SlotConst typv\u00e4rde felaktighet - -message.autofill.failed = Kan inte f\u00e5 statistik koden f\u00f6r automatisk kropps-parametrar.\r\nAvmarkera automatisk ifyllnad f\u00f6r att undvika det h\u00e4r meddelandet. -info.selecttrait = V\u00e4lj klass och klicka p\u00e5 en egenskap i Actionskript k\u00e4llan f\u00f6r att redigera den. - -button.viewgraph = Visa Diagram -button.viewhex = Visa Hex - -abc.traitslist.instanceinitializer = instans initierare -abc.traitslist.classinitializer = klass initierare - -action.edit.experimental = (experimentellt) - -message.action.saved = Koden har sparats - -error.action.save = %error% p\u00e5 rad %line% - -message.confirm.remove = \u00c4r du s\u00e4ker p\u00e5 att du vill ta bort %item% \n och alla objekt som \u00e4r beroende av den? - -#after version 1.6.5u1: - -button.ok = Godk\u00e4nn -button.cancel = Avbryt - -font.name = Typsnitts namn: -font.isbold = \u00c4r fet: -font.isitalic = \u00c4r kursiv: -font.ascent = Stigande: -font.descent = Nedstigande: -font.leading = Ledande: -font.characters = Bokst\u00e4ver: -font.characters.add = L\u00e4gg till bokst\u00e4ver: -value.unknown = ? - -yes = ja -no = nej - -errors.present = Det finns FEL i loggen. Klicka f\u00f6r att visa loggen. -errors.none = Det finns inga fel i loggen - -#after version 1.6.6: - -dialog.message.title = Meddelande -dialog.select.title = V\u00e4lj ett alternativ - -button.yes = Ja -button.no = Nej - -FileChooser.openButtonText = \u00d6ppna -FileChooser.openButtonToolTipText = \u00d6ppna -FileChooser.lookInLabelText = Alla Filer -FileChooser.acceptAllFileFilterText = Kolla i: -FileChooser.filesOfTypeLabelText = Filformat: -FileChooser.fileNameLabelText = Filnamn: -FileChooser.listViewButtonToolTipText = Lista -FileChooser.listViewButtonAccessibleName = Lista -FileChooser.detailsViewButtonToolTipText = Detaljer -FileChooser.detailsViewButtonAccessibleName = Detaljer -FileChooser.upFolderToolTipText = Upp en niv\u00e5 -FileChooser.upFolderAccessibleName = Upp en niv\u00e5 -FileChooser.homeFolderToolTipText = Hem -FileChooser.homeFolderAccessibleName = Hem -FileChooser.fileNameHeaderText = Namn -FileChooser.fileSizeHeaderText = Storlek -FileChooser.fileTypeHeaderText = Typ -FileChooser.fileDateHeaderText = Datum -FileChooser.fileAttrHeaderText = Egenskaper -FileChooser.openDialogTitleText = \u00d6ppna -FileChooser.directoryDescriptionText = Katalog -FileChooser.directoryOpenButtonText = \u00d6ppna -FileChooser.directoryOpenButtonToolTipText = \u00d6ppna vald katalog -FileChooser.fileDescriptionText = Generic File -FileChooser.helpButtonText = Hj\u00e4lp -FileChooser.helpButtonToolTipText = FileChooser help -FileChooser.newFolderAccessibleName = Ny mapp -FileChooser.newFolderErrorText = N\u00e5got gick fel n\u00e4r den f\u00f6rs\u00f6kta skapa en ny mapp -FileChooser.newFolderToolTipText = Skapa ny mapp -FileChooser.other.newFolder = NyMapp -FileChooser.other.newFolder.subsequent = NyMapp.{0} -FileChooser.win32.newFolder = Ny mapp -FileChooser.win32.newFolder.subsequent = Ny mapp ({0}) -FileChooser.saveButtonText = Spara -FileChooser.saveButtonToolTipText = Spara vald fil -FileChooser.saveDialogTitleText = Spara -FileChooser.saveInLabelText = Spara i: -FileChooser.updateButtonText = Uppdatera -FileChooser.updateButtonToolTipText = Uppdatera kataloglistning - -#after version 1.6.6u2: - -FileChooser.detailsViewActionLabel.textAndMnemonic = Detaljer -FileChooser.detailsViewButtonToolTip.textAndMnemonic = Detaljer -FileChooser.fileAttrHeader.textAndMnemonic = Egenskaper -FileChooser.fileDateHeader.textAndMnemonic = Modifierad -FileChooser.fileNameHeader.textAndMnemonic = Namn -FileChooser.fileNameLabel.textAndMnemonic = Filnamn: -FileChooser.fileSizeHeader.textAndMnemonic = Storlek -FileChooser.fileTypeHeader.textAndMnemonic = Typ -FileChooser.filesOfTypeLabel.textAndMnemonic = Filformat: -FileChooser.folderNameLabel.textAndMnemonic = Mappnamn: -FileChooser.homeFolderToolTip.textAndMnemonic = Hem -FileChooser.listViewActionLabel.textAndMnemonic = Lista -FileChooser.listViewButtonToolTip.textAndMnemonic = Lista -FileChooser.lookInLabel.textAndMnemonic = Kolla i: -FileChooser.newFolderActionLabel.textAndMnemonic = Ny mapp -FileChooser.newFolderToolTip.textAndMnemonic = Skapa Ny Mapp -FileChooser.refreshActionLabel.textAndMnemonic = Refresh -FileChooser.saveInLabel.textAndMnemonic = Spara i: -FileChooser.upFolderToolTip.textAndMnemonic = Upp en niv\u00e5 -FileChooser.viewMenuButtonAccessibleName = Visa meny -FileChooser.viewMenuButtonToolTipText = Visa meny -FileChooser.viewMenuLabel.textAndMnemonic = Visa -FileChooser.newFolderActionLabelText = Ny mapp -FileChooser.listViewActionLabelText = Lista -FileChooser.detailsViewActionLabelText = Detaljer -FileChooser.refreshActionLabelText = Uppdatera -FileChooser.sortMenuLabelText = Ordna ikoner efter -FileChooser.viewMenuLabelText = Visa -FileChooser.fileSizeKiloBytes = {0} KB -FileChooser.fileSizeMegaBytes = {0} MB -FileChooser.fileSizeGigaBytes = {0} GB -FileChooser.folderNameLabelText = Mappnamn: - -error.occured = Ett fel uppstod : %error% -button.abort = Avbryt -button.retry = F\u00f6rs\u00f6k igen -button.ignore = Ignorera - -font.source = Typsnitts k\u00e4lla: - -#after version 1.6.7: - -menu.export = Exportera -menu.general = Allm\u00e4nt -menu.language = Spr\u00e5k start. - -startup.welcometo = V\u00e4lkommen till -startup.selectopen = Klicka p\u00e5 ikonen \u00d6ppna p\u00e5 den \u00f6vre panelen eller dra SWF-filen till f\u00f6nstret f\u00f6r att starta. - -error.font.nocharacter = Vald teckensnitt-k\u00e4lla inneh\u00e5ller inte bokstav "%char%". - -warning.initializers = Statiska f\u00e4lt och consts initieras i initierare ofta.\nRedigera v\u00e4rdet h\u00e4r \u00e4r oftast inte tillr\u00e4ckligt! - -#after version 1.7.0u1: - -menu.tools.searchMemory = S\u00f6k efter SWFs i minnet -menu.file.reload = Ladda om -message.confirm.reload = Denna \u00e5tg\u00e4rd avbryter alla \u00e4ndringar som inte sparats och laddar om SWF filen igen.\nVill du forts\u00e4tta? - -dialog.selectbkcolor.title = V\u00e4lj bakgrundsf\u00e4rg f\u00f6r SWF display -button.selectbkcolor.hint = V\u00e4lj bakgrundsf\u00e4rg - -ColorChooser.okText = Acceptera -ColorChooser.cancelText = Avbryt -ColorChooser.resetText = \u00c5terst\u00e4ll -ColorChooser.previewText = F\u00f6rhandsvisning -ColorChooser.swatchesNameText = F\u00e4rgrutor -ColorChooser.swatchesRecentText = Nyligen: -ColorChooser.sampleText=Exempel Text Exempel Text - -#after version 1.7.1: - -preview.play = Spela -preview.pause = Pausa -preview.stop = Stoppa - -message.confirm.removemultiple = \u00c4r du s\u00e4ker p\u00e5 att du vill ta bort %count% objekt\noch alla andra objekt som \u00e4r beroende av objektet? - -menu.tools.searchCache = S\u00f6k i webbl\u00e4sarens cache - -#after version 1.7.2u2 - -error.trait.exists = Egenskap med namnet "%name%" finns redan. -button.addtrait = L\u00e4gg till egenskap -button.font.embed = Inb\u00e4dda... -button.yes.all = Ja till alla -button.no.all = Nej till alla -message.font.add.exists = Tecken %char% finns redan i typsnitts tag:en.\nVill du ers\u00e4tta den? - -filter.gfx = ScaleForm GFx filer (*.gfx) -filter.supported = Alla filtyper som st\u00f6ds -work.canceled = Avbruten -work.restoringControlFlow = \u00c5terst\u00e4llande fl\u00f6deskontroll -menu.advancedsettings.advancedsettings = Avancerade Inst\u00e4llningar -menu.recentFiles = Senaste Filerna - -#after version 1.7.4 -work.restoringControlFlow.complete = Reglerings fl\u00f6de \u00e5terst\u00e4llt -message.confirm.recentFileNotFound = Filen hittades inte. Vill du ta bort den fr\u00e5n senaste filer? -contextmenu.closeSwf = St\u00e4ng SWF -menu.settings.autoRenameIdentifiers = byt namn Automatisk p\u00e5 identifierare -menu.file.saveasexe = Spara som Exe... -filter.exe = K\u00f6rbara filer (*.exe) - -#after version 1.8.0 -font.updateTexts = Uppdatera texter - -#after version 1.8.0u1 -menu.file.close = St\u00e4ng -menu.file.closeAll = St\u00e4ng alla -menu.tools.otherTools = Annat -menu.tools.otherTools.clearRecentFiles = Rensa senaste filer -fontName.name = Typsnitt visningsnamn: -fontName.copyright = Typsnitt Upphovsr\u00e4tt: -button.preview = F\u00f6rhandsgranska -button.reset = \u00c5terst\u00e4ll -errors.info = Det \u00e4r information i loggen. Klicka f\u00f6r att visa. -errors.warning = Det \u00e4r varningar i loggen. Klicka f\u00f6r att visa.. - -decompilationError = Dekompilering felmeddelande - -disassemblingProgress.toString = toString -disassemblingProgress.reading = L\u00e4ser -disassemblingProgress.deobfuscating = Deobfuskering - -contextmenu.moveTag = Flytta tag till - -filter.swc = SWC komponent filer (*.swc) -filter.zip = ZIP komprimerade filer (*.zip) -filter.binary = Bin\u00e4r s\u00f6kning - alla filer (*.*) - -open.error = Fel -open.error.fileNotFound = Filen hittades inte -open.error.cannotOpen = Kan inte \u00f6ppna filen - -node.others = andra - -#after version 1.8.1 -menu.tools.search = Text S\u00f6kning - -#after version 1.8.1u1 -menu.tools.timeline = Tidslinje - -dialog.selectcolor.title = V\u00e4lj f\u00e4rg -button.selectcolor.hint = Klicka f\u00f6r att v\u00e4lja f\u00e4rg - -#default item name, will be used in following sentences -generictag.array.item = artikel -generictag.array.insertbeginning = Infoga %item% vid b\u00f6rjan -generictag.array.insertbefore = Infoga %item% f\u00f6re -generictag.array.remove = Tabort %item% -generictag.array.insertafter = Infoga %item% efter -generictag.array.insertend = Infoga %item% vid slutet - -#after version 2.0.0 -contextmenu.expandAll = Expandera alla -binaryData.truncateWarning = %count% bytes truncated. -filter.sounds = St\u00f6djande ljudformat (*.wav, *.mp3) -filter.sounds.wav = Wave filformat (*.wav) -filter.sounds.mp3 = MP3 komprimerat format (*.mp3) - -error.sound.invalid = Ogiltigt ljud. - -button.prev = F\u00f6reg\u00e5ende -button.next = N\u00e4sta - -#after version 2.1.0 -message.action.playerglobal.title = PlayerGlobal bibliotek beh\u00f6vs -message.action.playerglobal.needed = F\u00f6r ActionScript 3 direkt redigering, beh\u00f6vs ett bibliotek som kallas "PlayerGlobal.swc" det beh\u00f6vs laddas ned fr\u00e5n Adobe's hemsida.\r\n%adobehomepage%\r\nKlicka p\u00e5 okej f\u00f6r att g\u00e5 till nerladdningssidan. -message.action.playerglobal.place = Ladda ned biblioteket som kallas PlayerGlobal(.swc), och placera det i katalogen\r\n%libpath%\r\n Klica okej f\u00f6r att forts\u00e4tta. - -message.confirm.experimental.function = Denna funktion \u00e4r experimenterande. Det menas att du inte ska lita p\u00e5 resultaten och SWF-filen kan bli ej fungerande efter sparning. -message.confirm.donotshowagain = Visa inte igen - -menu.import = Importera -menu.file.import.text = Importera text -import.select.directory = V\u00e4lj kategori som du vill importera -error.text.import = Fel uppstod under text importering. Vill du forts\u00e4tta? - -#after version 2.1.1 -contextmenu.removeWithDependencies = Bort med beroenden - -abc.action.find-usages = Hitta anv\u00e4ndningar -abc.action.find-declaration = Hitta f\u00f6rklaring - -contextmenu.rawEdit = Raw \u00e4ndring -contextmenu.jumpToCharacter = Hoppa till tecken - -menu.settings.dumpView = Dump vy - -menu.view = Vy -menu.file.view.resources = Resurser -menu.file.view.hex = Hex dumpning - -node.header = header - -header.signature = Signature: -header.compression = Kompression: -header.compression.lzma = LZMA -header.compression.zlib = ZLIB -header.compression.none = Ingen kompression -header.version = SWF Version: -header.gfx = GFX: -header.filesize = Fil storlek: -header.framerate = Ram hastighet: -header.framecount = Ram r\u00e4knare: -header.displayrect = Visa rect: -header.displayrect.value.twips = %xmin%,%ymin% = > %xmax%,%ymax% twips -header.displayrect.value.pixels = %xmin%,%ymin% = > %xmax%,%ymax% pixlar - -#after version 2.1.2 -contextmenu.saveToFile = Spara till Fil -contextmenu.parseActions = Parse actions -contextmenu.parseABC = Parse ABC -contextmenu.parseInstructions = Parse AVM2 Instruktioner - -#after version 2.1.3 -menu.deobfuscation = AS1/2 Deobfuskering -menu.file.deobfuscation.old = Gammal stil -menu.file.deobfuscation.new = Ny stil - -#after version 2.1.4 -contextmenu.openswfinside = \u00d6ppna SWF inuti -binarydata.swfInside = Det ser ut som om det \u00e4r en SWF inuti denna bin\u00e4ra data tagg. Klicka h\u00e4r f\u00f6r att ladda det som subtree. - -#after version 3.0.0 -button.zoomin.hint = Zooma in -button.zoomout.hint = Zooma ut -button.zoomfit.hint = Zooma f\u00f6r att passa -button.zoomnone.hint = Zooma till 1:1 -button.snapshot.hint = Ta snapshot intill clipboard - -editorTruncateWarning = Text trunkerad vid position %chars% i debugg mode. - -#Font name which is presented in the SWF Font tag -font.name.intag = Typsnittsnamn i tagg: - -menu.debugger = Debugger -menu.debugger.switch = Debugger -menu.debugger.replacetrace = Ers\u00e4tt sp\u00e5rsamtal -menu.debugger.showlog = Visa Logg - -message.debugger = Denna SWF Debugger kan bara anv\u00e4ndas till att skriva ut meddelanden till logg f\u00f6nstret, webbl\u00e4sare konsol eller larm. Den \u00e4r INTE designad f\u00f6r egenskaper som step code, breakpoints och s\u00e5 vidare. - -contextmenu.addTag = L\u00e4gg till tagg - -deobfuscation.comment.tryenable = Tips: Du kan testa att aktivera "Automatisk deobfuskering" i Inst\u00e4llningar -deobfuscation.comment.failed = Deobfuskering \u00e4r aktiverad men dekompileringen slutf\u00f6rdes inte. Om filen INTE \u00e4r obfuskerad, inaktivera "Automatisk Deobfuskering" f\u00f6r ett b\u00e4ttre resultat. - -#after version 4.0.2 -preview.nextframe = N\u00e4sta ram -preview.prevframe = F\u00f6reg\u00e5ende ram -preview.gotoframe = G\u00e5 till ram... - -preview.gotoframe.dialog.title = G\u00e5 till ram -preview.gotoframe.dialog.message = Skriv in ram nummer (%min% - %max%) -preview.gotoframe.dialog.frame.error = Ogiltigt ram nummer. Det m\u00e5ste vara ett nummer mellan %min% och %max%. - -error.text.invalid.continue = Ogiltig text: %text% p\u00e5 rad %line%. Vill du forts\u00e4tta? - -#after version 4.0.5 -contextmenu.copyTag = Kopiera tagg till -fit = passa -button.setAdvanceValues = S\u00e4tt avancerade v\u00e4rden - -menu.tools.replace = Ers\u00e4tt text - -message.confirm.close = Det finns osparade f\u00f6r\u00e4ndringar. Vill du verkligen st\u00e4nga {swfName}? -message.confirm.closeAll = Det finns osparade f\u00f6r\u00e4ndringar. Vill du verkligen st\u00e4nga alla SWFs? - -contextmenu.exportJavaSource = Exportera Java K\u00e4lla -contextmenu.exportSwfXml = Exportera SWF som XML -contextmenu.importSwfXml = Importera SWF XML - -filter.xml = XML - -#after version 4.1.0 -contextmenu.undo = \u00c5ngra - -text.align.left = V\u00e4nster justering -text.align.right = H\u00f6ger justering -text.align.center = Mitt justering -text.align.justify = R\u00e4ttf\u00e4rdiga justering - -text.undo = \u00c5ngra f\u00f6r\u00e4ndringar - -menu.file.import.xml = Importera SWF XML -menu.file.export.xml = Exportera SWF XML - -#after version 4.1.1 -text.align.translatex.decrease = Minska TranslateX -text.align.translatex.increase = \u00d6ka TranslateX -selectPreviousTag = V\u00e4lj f\u00f6reg\u00e5ende tagg -selectNextTag = V\u00e4lj n\u00e4sta tagg -button.ignoreAll = Ignorera Allt -menu.file.import.symbolClass = Symbol Klass -text.toggleCase = S\u00e4tter p\u00e5 eller st\u00e4nger av fallet - -#after version 5.0.2 -preview.loop = Repetera -menu.file.import.script = Importera skript -contextmenu.copyTagWithDependencies = Kopiera tag med beroenden till -button.replaceWithTag = Ers\u00e4tt med andra tecken tag -button.resolveConstants = L\u00f6sa constants - -#after version 5.1.0 -button.viewConstants = Granska Constants -work.exported = Exporterad -button.replaceAlphaChannel = Ers\u00e4tt alfakanal... - -tagInfo.header.name = Namn -tagInfo.header.value = V\u00e4rde -tagInfo.tagType = Tag Typ -tagInfo.characterId = Tecken Id -tagInfo.offset = Offset -tagInfo.length = L\u00e4ngd -tagInfo.bounds = Gr\u00e4nser -tagInfo.width = Bredd -tagInfo.height = H\u00f6jd -tagInfo.neededCharacters = Beh\u00f6vande Tecken - -button.viewhexpcode = Granska Hex med instruktioner -taginfo.header = Grundl\u00e4ggande tag information - -tagInfo.dependentCharacters = Beroende Tecken - -#after version 5.3.0 -header.uncompressed = Okomprimerad -header.warning.unsupportedGfxCompression = GFX st\u00f6der endast okomprimerat eller Zlib komprimerad inneh\u00e5ll. -header.warning.minimumZlibVersion = Zlib kompression beh\u00f6ver SWF version 6 eller st\u00f6rre. -header.warning.minimumLzmaVersion = LZMA kompression beh\u00f6ver SWF version 13 eller st\u00f6rre. - -filter.dmg = Mac K\u00f6rbara filer (*.dmg) -filter.linuxExe = Linux K\u00f6rbara filer +# Copyright (C) 2010-2015 JPEXS +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +menu.file = Fil +menu.file.open = \u00d6ppna... +menu.file.save = Spara +menu.file.saveas = Spara som... +menu.file.export.fla = Exportera till FLA +menu.file.export.all = Exportera alla delar +menu.file.export.selection = Exportera markering +menu.file.exit = St\u00e4ng + +menu.tools = Verktyg +menu.tools.searchas = S\u00f6k igenom alla ActionSkript... +menu.tools.proxy = Proxy +menu.tools.deobfuscation = Avl\u00e4gsna obfuskering +menu.tools.deobfuscation.pcode = Avl\u00e4gsna obfuskerad Bytekod... +menu.tools.deobfuscation.globalrename = Byt namn p\u00e5 global identifierare +menu.tools.deobfuscation.renameinvalid = Byt namn p\u00e5 felaktiga identifierare +menu.tools.gotoDocumentClass = G\u00e5 till dokumentklass + +menu.settings = Inst\u00e4llningar +menu.settings.autodeobfuscation = Automatiskt avl\u00e4gsning av obfuskering +menu.settings.internalflashviewer = Anv\u00e4nd egen Flash-spelare +menu.settings.parallelspeedup = Parallell uppsnabbning +menu.settings.disabledecompilation = Inaktivera dekompilering (Demontera endast) +menu.settings.addtocontextmenu = L\u00e4gg till FFDec till SWF-filernas snabbmeny +menu.settings.language = Byt spr\u00e5k +menu.settings.cacheOnDisk = Anv\u00e4nd cachelagring p\u00e5 h\u00e5rddisken +menu.settings.gotoMainClassOnStartup = Markera dokumentklass vid uppstart + +menu.help = Hj\u00e4lp +menu.help.checkupdates = Leta efter uppdateringar... +menu.help.helpus = Hj\u00e4lp oss! +menu.help.homepage = Bes\u00f6k hemsidan +menu.help.about = Om... + +contextmenu.remove = Ta bort + +button.save = Spara +button.edit = \u00c4ndra +button.cancel = \u00c5ngra +button.replace = Ers\u00e4tt... + +notavailonthisplatform = F\u00f6rhandsgranskning av detta objekt \u00e4r inte tillg\u00e4nglig p\u00e5 denna plattform. (Windows bara) + +swfpreview = SWF f\u00f6rhandsvisning +swfpreview.internal = SWF f\u00f6rhandsvisning (Intern f\u00f6rhandsvisning) + +parameters = Parametrar + +rename.enternew = Ange det nya namnet: + +rename.finished.identifier = Identifierare omd\u00f6pt. +rename.finished.multiname = %count% multiname har blivit omd\u00f6pt(a). + +node.texts = texter +node.images = bilder +node.movies = filmer +node.sounds = ljud +node.binaryData = bin\u00e4rData +node.fonts = teckensnitt +node.sprites = sprites +node.shapes = former +node.morphshapes = morphform +node.buttons = knappar +node.frames = ramar +node.scripts = skript + +message.warning = Varning +message.confirm.experimental = F\u00f6ljande tillv\u00e4gag\u00e5ngss\u00e4tt kan skada SWF-filen som kan d\u00e4refter bli ospelbar.\r\nANV\u00c4ND DEN P\u00c5 DIN EGEN RISK. Vill du forts\u00e4tta? +message.confirm.parallel = Parallellitet kan snabba upp laddning och dekompilering, men anv\u00e4nda mera minne. +message.confirm.on = Vill du aktivera detta? +message.confirm.off = Vill du avaktivera detta? +message.confirm = Bekr\u00e4fta + +message.confirm.autodeobfuscate = Automatiskt avl\u00e4gsning av obfuskering \u00e4r ett s\u00e4tt till att dekompilera obfuskerad kod.\r\nAvl\u00e4gsna obfuskerad kod leder till sl\u00f6are dekompilering och n\u00e5gon d\u00f6d kod kan bli borttagen..\r\nOm koden inte \u00e4r obfuskerad, s\u00e5 \u00e4r det b\u00e4ttre att st\u00e4nga av automatisk borttagning av obfuskering. + +message.parallel = parallellitet +message.trait.saved = Egenskap har sparats + +message.constant.new.string = Str\u00e4ng "%value%" finns inte i konstant tabellen. Vill du l\u00e4gga till det? +message.constant.new.string.title = L\u00e4gg till Str\u00e4ng +message.constant.new.integer = Heltal v\u00e4rde "%value%" finns inte i konstant tabellen. Vill du l\u00e4gga till det? +message.constant.new.integer.title = L\u00e4gg till Heltal +message.constant.new.unsignedinteger = Osignerat heltal v\u00e4rde "%value%" finns inte i konstant tabellen. Vill du l\u00e4gga till det? +message.constant.new.unsignedinteger.title = L\u00e4gg till Osignerat heltal +message.constant.new.double = Dubbelt v\u00e4rde "%value%" finns inte i konstant tabellen. Vill du l\u00e4gga till det? +message.constant.new.double.title = L\u00e4gg till Dubbel + +work.buffering = Buffrar +work.waitingfordissasembly = V\u00e4ntar p\u00e5 demontering +work.gettinghilights = Getting hilights +work.disassembling = Demonterar +work.exporting = Exporterar +work.searching = S\u00f6ker +work.renaming = \u00c4ndrar namn +work.exporting.fla = Exporterar FLA +work.renaming.identifiers = \u00c4ndrar namn p\u00e5 identifierare +work.deobfuscating = Avl\u00e4gsning utav obfuskering +work.decompiling = Dekompilering +work.gettingvariables = Tar variablar +work.reading.swf = L\u00e4ser SWF +work.creatingwindow = Skapar f\u00f6nster +work.buildingscripttree = Bygger skript tr\u00e4 + +work.deobfuscating.complete = Avl\u00e4gsning utav obfuskering \u00e4r nu f\u00e4rdig + +message.search.notfound = Str\u00e4ng "%searchtext%" hittades inte. +message.search.notfound.title = Hittades inte + +message.rename.notfound.multiname = Ingen multiname hittades under mark\u00f6ren +message.rename.notfound.identifier = ingen identifiering hittades under mark\u00f6ren +message.rename.notfound.title = Hittades inte +message.rename.renamed = Identifierare som har \u00e4ndrat namn: %count% + +filter.images = Bilder (*.jpg,*.gif,*.png,*.bmp) +filter.fla = %version% Dokument (*.fla) +filter.xfl = %version% Okomprimerat Dokument (*.xfl) +filter.swf = SWF filer (*.swf) + +error = Fel +error.image.invalid = Ogiltig bild. + +error.text.invalid = Ogiltig text: %text% p\u00e5 rad %line% +error.file.save = Kan inte spara filen +error.file.write = Kan inte skriva till filen +error.export = Fel under loppet av exporteringen + +export.select.directory = V\u00e4lj s\u00f6kv\u00e4g till katalog att exportera +export.finishedin = Exporterades i %time% + +update.check.title = Uppdaterings koll +update.check.nonewversion = Ingen ny version finns tillg\u00e4nglig. + +message.helpus = V\u00e4nligen bes\u00f6k\r\n%url%\r\nf\u00f6r mer detaljer. +message.homepage = Bes\u00f6k hemsidan: \r\n%url% + +proxy = Proxy +proxy.start = Starta proxy +proxy.stop = Stoppa proxy +proxy.show = Visa proxy +exit = St\u00e4ng + +panel.disassembled = P-code k\u00e4llkod +panel.decompiled = ActionSkript k\u00e4llkod + +search.info = S\u00f6k efter "%text%" : +search.script = Skript + +constants = Konstanter +traits = Egenskaper + +pleasewait = V\u00e4nligen v\u00e4nta + +abc.detail.methodtrait = Metod/F\u00e5ngare/Egenskap s\u00e4ttare +abc.detail.unsupported = - +abc.detail.slotconsttrait = Slot/Const Egenskap +abc.detail.traitname = Namn: + +abc.detail.body.params.maxstack = Maximal stapling: +abc.detail.body.params.localregcount = Lokala register r\u00e4knade: +abc.detail.body.params.minscope = Minsta omfattnings djup: +abc.detail.body.params.maxscope = Maximal omfattnings djup: +abc.detail.body.params.autofill = Automatisk utfyllnad n\u00e4r koden sparas (GLOBAL INST\u00c4LLNING) +abc.detail.body.params.autofill.experimental = ...EXPERIMENTELL + +abc.detail.methodinfo.methodindex = Metod register: +abc.detail.methodinfo.parameters = Parametrar: +abc.detail.methodinfo.returnvalue = \u00c5terl\u00e4mna v\u00e4rde: + +error.methodinfo.params = MetodInfo Parameter fel +error.methodinfo.returnvalue = MetodInfo \u00e5terl\u00e4mmnings typ Fel + +abc.detail.methodinfo = MetodInfo +abc.detail.body.code = MetodInfo Kod +abc.detail.body.params = MetodKropp parametrar + +abc.detail.slotconst.typevalue = Typ och V\u00e4rde: + +error.slotconst.typevalue = SlotConst typv\u00e4rde felaktighet + +message.autofill.failed = Kan inte f\u00e5 statistik koden f\u00f6r automatisk kropps-parametrar.\r\nAvmarkera automatisk ifyllnad f\u00f6r att undvika det h\u00e4r meddelandet. +info.selecttrait = V\u00e4lj klass och klicka p\u00e5 en egenskap i Actionskript k\u00e4llan f\u00f6r att redigera den. + +button.viewgraph = Visa Diagram +button.viewhex = Visa Hex + +abc.traitslist.instanceinitializer = instans initierare +abc.traitslist.classinitializer = klass initierare + +action.edit.experimental = (experimentellt) + +message.action.saved = Koden har sparats + +error.action.save = %error% p\u00e5 rad %line% + +message.confirm.remove = \u00c4r du s\u00e4ker p\u00e5 att du vill ta bort %item% \n och alla objekt som \u00e4r beroende av den? + +#after version 1.6.5u1: + +button.ok = Godk\u00e4nn +button.cancel = Avbryt + +font.name = Typsnitts namn: +font.isbold = \u00c4r fet: +font.isitalic = \u00c4r kursiv: +font.ascent = Stigande: +font.descent = Nedstigande: +font.leading = Ledande: +font.characters = Bokst\u00e4ver: +font.characters.add = L\u00e4gg till bokst\u00e4ver: +value.unknown = ? + +yes = ja +no = nej + +errors.present = Det finns FEL i loggen. Klicka f\u00f6r att visa loggen. +errors.none = Det finns inga fel i loggen + +#after version 1.6.6: + +dialog.message.title = Meddelande +dialog.select.title = V\u00e4lj ett alternativ + +button.yes = Ja +button.no = Nej + +FileChooser.openButtonText = \u00d6ppna +FileChooser.openButtonToolTipText = \u00d6ppna +FileChooser.lookInLabelText = Alla Filer +FileChooser.acceptAllFileFilterText = Kolla i: +FileChooser.filesOfTypeLabelText = Filformat: +FileChooser.fileNameLabelText = Filnamn: +FileChooser.listViewButtonToolTipText = Lista +FileChooser.listViewButtonAccessibleName = Lista +FileChooser.detailsViewButtonToolTipText = Detaljer +FileChooser.detailsViewButtonAccessibleName = Detaljer +FileChooser.upFolderToolTipText = Upp en niv\u00e5 +FileChooser.upFolderAccessibleName = Upp en niv\u00e5 +FileChooser.homeFolderToolTipText = Hem +FileChooser.homeFolderAccessibleName = Hem +FileChooser.fileNameHeaderText = Namn +FileChooser.fileSizeHeaderText = Storlek +FileChooser.fileTypeHeaderText = Typ +FileChooser.fileDateHeaderText = Datum +FileChooser.fileAttrHeaderText = Egenskaper +FileChooser.openDialogTitleText = \u00d6ppna +FileChooser.directoryDescriptionText = Katalog +FileChooser.directoryOpenButtonText = \u00d6ppna +FileChooser.directoryOpenButtonToolTipText = \u00d6ppna vald katalog +FileChooser.fileDescriptionText = Generic File +FileChooser.helpButtonText = Hj\u00e4lp +FileChooser.helpButtonToolTipText = FileChooser help +FileChooser.newFolderAccessibleName = Ny mapp +FileChooser.newFolderErrorText = N\u00e5got gick fel n\u00e4r den f\u00f6rs\u00f6kta skapa en ny mapp +FileChooser.newFolderToolTipText = Skapa ny mapp +FileChooser.other.newFolder = NyMapp +FileChooser.other.newFolder.subsequent = NyMapp.{0} +FileChooser.win32.newFolder = Ny mapp +FileChooser.win32.newFolder.subsequent = Ny mapp ({0}) +FileChooser.saveButtonText = Spara +FileChooser.saveButtonToolTipText = Spara vald fil +FileChooser.saveDialogTitleText = Spara +FileChooser.saveInLabelText = Spara i: +FileChooser.updateButtonText = Uppdatera +FileChooser.updateButtonToolTipText = Uppdatera kataloglistning + +#after version 1.6.6u2: + +FileChooser.detailsViewActionLabel.textAndMnemonic = Detaljer +FileChooser.detailsViewButtonToolTip.textAndMnemonic = Detaljer +FileChooser.fileAttrHeader.textAndMnemonic = Egenskaper +FileChooser.fileDateHeader.textAndMnemonic = Modifierad +FileChooser.fileNameHeader.textAndMnemonic = Namn +FileChooser.fileNameLabel.textAndMnemonic = Filnamn: +FileChooser.fileSizeHeader.textAndMnemonic = Storlek +FileChooser.fileTypeHeader.textAndMnemonic = Typ +FileChooser.filesOfTypeLabel.textAndMnemonic = Filformat: +FileChooser.folderNameLabel.textAndMnemonic = Mappnamn: +FileChooser.homeFolderToolTip.textAndMnemonic = Hem +FileChooser.listViewActionLabel.textAndMnemonic = Lista +FileChooser.listViewButtonToolTip.textAndMnemonic = Lista +FileChooser.lookInLabel.textAndMnemonic = Kolla i: +FileChooser.newFolderActionLabel.textAndMnemonic = Ny mapp +FileChooser.newFolderToolTip.textAndMnemonic = Skapa Ny Mapp +FileChooser.refreshActionLabel.textAndMnemonic = Refresh +FileChooser.saveInLabel.textAndMnemonic = Spara i: +FileChooser.upFolderToolTip.textAndMnemonic = Upp en niv\u00e5 +FileChooser.viewMenuButtonAccessibleName = Visa meny +FileChooser.viewMenuButtonToolTipText = Visa meny +FileChooser.viewMenuLabel.textAndMnemonic = Visa +FileChooser.newFolderActionLabelText = Ny mapp +FileChooser.listViewActionLabelText = Lista +FileChooser.detailsViewActionLabelText = Detaljer +FileChooser.refreshActionLabelText = Uppdatera +FileChooser.sortMenuLabelText = Ordna ikoner efter +FileChooser.viewMenuLabelText = Visa +FileChooser.fileSizeKiloBytes = {0} KB +FileChooser.fileSizeMegaBytes = {0} MB +FileChooser.fileSizeGigaBytes = {0} GB +FileChooser.folderNameLabelText = Mappnamn: + +error.occured = Ett fel uppstod : %error% +button.abort = Avbryt +button.retry = F\u00f6rs\u00f6k igen +button.ignore = Ignorera + +font.source = Typsnitts k\u00e4lla: + +#after version 1.6.7: + +menu.export = Exportera +menu.general = Allm\u00e4nt +menu.language = Spr\u00e5k start. + +startup.welcometo = V\u00e4lkommen till +startup.selectopen = Klicka p\u00e5 ikonen \u00d6ppna p\u00e5 den \u00f6vre panelen eller dra SWF-filen till f\u00f6nstret f\u00f6r att starta. + +error.font.nocharacter = Vald teckensnitt-k\u00e4lla inneh\u00e5ller inte bokstav "%char%". + +warning.initializers = Statiska f\u00e4lt och consts initieras i initierare ofta.\nRedigera v\u00e4rdet h\u00e4r \u00e4r oftast inte tillr\u00e4ckligt! + +#after version 1.7.0u1: + +menu.tools.searchMemory = S\u00f6k efter SWFs i minnet +menu.file.reload = Ladda om +message.confirm.reload = Denna \u00e5tg\u00e4rd avbryter alla \u00e4ndringar som inte sparats och laddar om SWF filen igen.\nVill du forts\u00e4tta? + +dialog.selectbkcolor.title = V\u00e4lj bakgrundsf\u00e4rg f\u00f6r SWF display +button.selectbkcolor.hint = V\u00e4lj bakgrundsf\u00e4rg + +ColorChooser.okText = Acceptera +ColorChooser.cancelText = Avbryt +ColorChooser.resetText = \u00c5terst\u00e4ll +ColorChooser.previewText = F\u00f6rhandsvisning +ColorChooser.swatchesNameText = F\u00e4rgrutor +ColorChooser.swatchesRecentText = Nyligen: +ColorChooser.sampleText=Exempel Text Exempel Text + +#after version 1.7.1: + +preview.play = Spela +preview.pause = Pausa +preview.stop = Stoppa + +message.confirm.removemultiple = \u00c4r du s\u00e4ker p\u00e5 att du vill ta bort %count% objekt\noch alla andra objekt som \u00e4r beroende av objektet? + +menu.tools.searchCache = S\u00f6k i webbl\u00e4sarens cache + +#after version 1.7.2u2 + +error.trait.exists = Egenskap med namnet "%name%" finns redan. +button.addtrait = L\u00e4gg till egenskap +button.font.embed = Inb\u00e4dda... +button.yes.all = Ja till alla +button.no.all = Nej till alla +message.font.add.exists = Tecken %char% finns redan i typsnitts tag:en.\nVill du ers\u00e4tta den? + +filter.gfx = ScaleForm GFx filer (*.gfx) +filter.supported = Alla filtyper som st\u00f6ds +work.canceled = Avbruten +work.restoringControlFlow = \u00c5terst\u00e4llande fl\u00f6deskontroll +menu.advancedsettings.advancedsettings = Avancerade Inst\u00e4llningar +menu.recentFiles = Senaste Filerna + +#after version 1.7.4 +work.restoringControlFlow.complete = Reglerings fl\u00f6de \u00e5terst\u00e4llt +message.confirm.recentFileNotFound = Filen hittades inte. Vill du ta bort den fr\u00e5n senaste filer? +contextmenu.closeSwf = St\u00e4ng SWF +menu.settings.autoRenameIdentifiers = byt namn Automatisk p\u00e5 identifierare +menu.file.saveasexe = Spara som Exe... +filter.exe = K\u00f6rbara filer (*.exe) + +#after version 1.8.0 +font.updateTexts = Uppdatera texter + +#after version 1.8.0u1 +menu.file.close = St\u00e4ng +menu.file.closeAll = St\u00e4ng alla +menu.tools.otherTools = Annat +menu.tools.otherTools.clearRecentFiles = Rensa senaste filer +fontName.name = Typsnitt visningsnamn: +fontName.copyright = Typsnitt Upphovsr\u00e4tt: +button.preview = F\u00f6rhandsgranska +button.reset = \u00c5terst\u00e4ll +errors.info = Det \u00e4r information i loggen. Klicka f\u00f6r att visa. +errors.warning = Det \u00e4r varningar i loggen. Klicka f\u00f6r att visa.. + +decompilationError = Dekompilering felmeddelande + +disassemblingProgress.toString = toString +disassemblingProgress.reading = L\u00e4ser +disassemblingProgress.deobfuscating = Deobfuskering + +contextmenu.moveTag = Flytta tag till + +filter.swc = SWC komponent filer (*.swc) +filter.zip = ZIP komprimerade filer (*.zip) +filter.binary = Bin\u00e4r s\u00f6kning - alla filer (*.*) + +open.error = Fel +open.error.fileNotFound = Filen hittades inte +open.error.cannotOpen = Kan inte \u00f6ppna filen + +node.others = andra + +#after version 1.8.1 +menu.tools.search = Text S\u00f6kning + +#after version 1.8.1u1 +menu.tools.timeline = Tidslinje + +dialog.selectcolor.title = V\u00e4lj f\u00e4rg +button.selectcolor.hint = Klicka f\u00f6r att v\u00e4lja f\u00e4rg + +#default item name, will be used in following sentences +generictag.array.item = artikel +generictag.array.insertbeginning = Infoga %item% vid b\u00f6rjan +generictag.array.insertbefore = Infoga %item% f\u00f6re +generictag.array.remove = Tabort %item% +generictag.array.insertafter = Infoga %item% efter +generictag.array.insertend = Infoga %item% vid slutet + +#after version 2.0.0 +contextmenu.expandAll = Expandera alla +binaryData.truncateWarning = %count% bytes truncated. +filter.sounds = St\u00f6djande ljudformat (*.wav, *.mp3) +filter.sounds.wav = Wave filformat (*.wav) +filter.sounds.mp3 = MP3 komprimerat format (*.mp3) + +error.sound.invalid = Ogiltigt ljud. + +button.prev = F\u00f6reg\u00e5ende +button.next = N\u00e4sta + +#after version 2.1.0 +message.action.playerglobal.title = PlayerGlobal bibliotek beh\u00f6vs +message.action.playerglobal.needed = F\u00f6r ActionScript 3 direkt redigering, beh\u00f6vs ett bibliotek som kallas "PlayerGlobal.swc" det beh\u00f6vs laddas ned fr\u00e5n Adobe's hemsida.\r\n%adobehomepage%\r\nKlicka p\u00e5 okej f\u00f6r att g\u00e5 till nerladdningssidan. +message.action.playerglobal.place = Ladda ned biblioteket som kallas PlayerGlobal(.swc), och placera det i katalogen\r\n%libpath%\r\n Klica okej f\u00f6r att forts\u00e4tta. + +message.confirm.experimental.function = Denna funktion \u00e4r experimenterande. Det menas att du inte ska lita p\u00e5 resultaten och SWF-filen kan bli ej fungerande efter sparning. +message.confirm.donotshowagain = Visa inte igen + +menu.import = Importera +menu.file.import.text = Importera text +import.select.directory = V\u00e4lj kategori som du vill importera +error.text.import = Fel uppstod under text importering. Vill du forts\u00e4tta? + +#after version 2.1.1 +contextmenu.removeWithDependencies = Bort med beroenden + +abc.action.find-usages = Hitta anv\u00e4ndningar +abc.action.find-declaration = Hitta f\u00f6rklaring + +contextmenu.rawEdit = Raw \u00e4ndring +contextmenu.jumpToCharacter = Hoppa till tecken + +menu.settings.dumpView = Dump vy + +menu.view = Vy +menu.file.view.resources = Resurser +menu.file.view.hex = Hex dumpning + +node.header = header + +header.signature = Signature: +header.compression = Kompression: +header.compression.lzma = LZMA +header.compression.zlib = ZLIB +header.compression.none = Ingen kompression +header.version = SWF Version: +header.gfx = GFX: +header.filesize = Fil storlek: +header.framerate = Ram hastighet: +header.framecount = Ram r\u00e4knare: +header.displayrect = Visa rect: +header.displayrect.value.twips = %xmin%,%ymin% = > %xmax%,%ymax% twips +header.displayrect.value.pixels = %xmin%,%ymin% = > %xmax%,%ymax% pixlar + +#after version 2.1.2 +contextmenu.saveToFile = Spara till Fil +contextmenu.parseActions = Parse actions +contextmenu.parseABC = Parse ABC +contextmenu.parseInstructions = Parse AVM2 Instruktioner + +#after version 2.1.3 +menu.deobfuscation = Deobfuskering +menu.file.deobfuscation.old = Gammal stil +menu.file.deobfuscation.new = Ny stil + +#after version 2.1.4 +contextmenu.openswfinside = \u00d6ppna SWF inuti +binarydata.swfInside = Det ser ut som om det \u00e4r en SWF inuti denna bin\u00e4ra data tagg. Klicka h\u00e4r f\u00f6r att ladda det som subtree. + +#after version 3.0.0 +button.zoomin.hint = Zooma in +button.zoomout.hint = Zooma ut +button.zoomfit.hint = Zooma f\u00f6r att passa +button.zoomnone.hint = Zooma till 1:1 +button.snapshot.hint = Ta snapshot intill clipboard + +editorTruncateWarning = Text trunkerad vid position %chars% i debugg mode. + +#Font name which is presented in the SWF Font tag +font.name.intag = Typsnittsnamn i tagg: + +menu.debugger = Debugger +menu.debugger.switch = Debugger +menu.debugger.replacetrace = Ers\u00e4tt sp\u00e5rsamtal +menu.debugger.showlog = Visa Logg + +message.debugger = Denna SWF Debugger kan bara anv\u00e4ndas till att skriva ut meddelanden till logg f\u00f6nstret, webbl\u00e4sare konsol eller larm. Den \u00e4r INTE designad f\u00f6r egenskaper som step code, breakpoints och s\u00e5 vidare. + +contextmenu.addTag = L\u00e4gg till tagg + +deobfuscation.comment.tryenable = Tips: Du kan testa att aktivera "Automatisk deobfuskering" i Inst\u00e4llningar +deobfuscation.comment.failed = Deobfuskering \u00e4r aktiverad men dekompileringen slutf\u00f6rdes inte. Om filen INTE \u00e4r obfuskerad, inaktivera "Automatisk Deobfuskering" f\u00f6r ett b\u00e4ttre resultat. + +#after version 4.0.2 +preview.nextframe = N\u00e4sta ram +preview.prevframe = F\u00f6reg\u00e5ende ram +preview.gotoframe = G\u00e5 till ram... + +preview.gotoframe.dialog.title = G\u00e5 till ram +preview.gotoframe.dialog.message = Skriv in ram nummer (%min% - %max%) +preview.gotoframe.dialog.frame.error = Ogiltigt ram nummer. Det m\u00e5ste vara ett nummer mellan %min% och %max%. + +error.text.invalid.continue = Ogiltig text: %text% p\u00e5 rad %line%. Vill du forts\u00e4tta? + +#after version 4.0.5 +contextmenu.copyTag = Kopiera tagg till +fit = passa +button.setAdvanceValues = S\u00e4tt avancerade v\u00e4rden + +menu.tools.replace = Ers\u00e4tt text + +message.confirm.close = Det finns osparade f\u00f6r\u00e4ndringar. Vill du verkligen st\u00e4nga {swfName}? +message.confirm.closeAll = Det finns osparade f\u00f6r\u00e4ndringar. Vill du verkligen st\u00e4nga alla SWFs? + +contextmenu.exportJavaSource = Exportera Java K\u00e4lla +contextmenu.exportSwfXml = Exportera SWF som XML +contextmenu.importSwfXml = Importera SWF XML + +filter.xml = XML + +#after version 4.1.0 +contextmenu.undo = \u00c5ngra + +text.align.left = V\u00e4nster justering +text.align.right = H\u00f6ger justering +text.align.center = Mitt justering +text.align.justify = R\u00e4ttf\u00e4rdiga justering + +text.undo = \u00c5ngra f\u00f6r\u00e4ndringar + +menu.file.import.xml = Importera SWF XML +menu.file.export.xml = Exportera SWF XML + +#after version 4.1.1 +text.align.translatex.decrease = Minska TranslateX +text.align.translatex.increase = \u00d6ka TranslateX +selectPreviousTag = V\u00e4lj f\u00f6reg\u00e5ende tagg +selectNextTag = V\u00e4lj n\u00e4sta tagg +button.ignoreAll = Ignorera Allt +menu.file.import.symbolClass = Symbol Klass +text.toggleCase = S\u00e4tter p\u00e5 eller st\u00e4nger av fallet + +#after version 5.0.2 +preview.loop = Repetera +menu.file.import.script = Importera skript +contextmenu.copyTagWithDependencies = Kopiera tag med beroenden till +button.replaceWithTag = Ers\u00e4tt med andra tecken tag +button.resolveConstants = L\u00f6sa constants + +#after version 5.1.0 +button.viewConstants = Granska Constants +work.exported = Exporterad +button.replaceAlphaChannel = Ers\u00e4tt alfakanal... + +tagInfo.header.name = Namn +tagInfo.header.value = V\u00e4rde +tagInfo.tagType = Tag Typ +tagInfo.characterId = Tecken Id +tagInfo.offset = Offset +tagInfo.length = L\u00e4ngd +tagInfo.bounds = Gr\u00e4nser +tagInfo.width = Bredd +tagInfo.height = H\u00f6jd +tagInfo.neededCharacters = Beh\u00f6vande Tecken + +button.viewhexpcode = Granska Hex med instruktioner +taginfo.header = Grundl\u00e4ggande tag information + +tagInfo.dependentCharacters = Beroende Tecken + +#after version 5.3.0 +header.uncompressed = Okomprimerad +header.warning.unsupportedGfxCompression = GFX st\u00f6der endast okomprimerat eller Zlib komprimerad inneh\u00e5ll. +header.warning.minimumZlibVersion = Zlib kompression beh\u00f6ver SWF version 6 eller st\u00f6rre. +header.warning.minimumLzmaVersion = LZMA kompression beh\u00f6ver SWF version 13 eller st\u00f6rre. + +filter.dmg = Mac K\u00f6rbara filer (*.dmg) +filter.linuxExe = Linux K\u00f6rbara filer diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_zh.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_zh.properties index 62d4741d2..0c79ca224 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_zh.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_zh.properties @@ -488,6 +488,6 @@ contextmenu.parseActions = \u89e3\u6790\u52a8\u4f5c contextmenu.parseABC = \u89e3\u6790ABC contextmenu.parseInstructions = \u89e3\u6790AVM2\u6307\u4ee4 -menu.deobfuscation = AS1/2 \u53cd\u6df7\u6dc6 +menu.deobfuscation = \u53cd\u6df7\u6dc6 menu.file.deobfuscation.old = \u65e7\u6837\u5f0f menu.file.deobfuscation.new = \u65b0\u6837\u5f0f From b286c45036e628fcab29ad7ed8db5c587d06328a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 21 Jun 2015 07:26:27 +0200 Subject: [PATCH 13/20] AS3: Lookupswitch offsets deobfuscation fix --- .../decompiler/flash/abc/avm2/AVM2Code.java | 58 +++++++++++++++---- .../flash/abc/avm2/graph/AVM2Graph.java | 2 +- .../abc/avm2/model/IntegerValueAVM2Item.java | 2 +- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 6b1bacd0b..81324e6c7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1872,30 +1872,68 @@ public class AVM2Code implements Cloneable { { for (int i = 0; i < pos; i++) { - for (int j = 0; j < code.get(i).definition.operands.length; j++) { - if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; + if (code.get(i).definition instanceof LookupSwitchIns) { + long target = code.get(i).offset + code.get(i).operands[0]; + if (target > instruction.offset) { + code.get(i).operands[0] += byteCount; + } + if (target == instruction.offset && !preRefsToThis) { + code.get(i).operands[0] += byteCount; + } + for (int k = 2; k < code.get(i).operands.length; k++) { + target = code.get(i).offset + code.get(i).operands[k]; if (target > instruction.offset) { - code.get(i).operands[j] += byteCount; + code.get(i).operands[k] += byteCount; } if (target == instruction.offset && !preRefsToThis) { - code.get(i).operands[j] += byteCount; + code.get(i).operands[k] += byteCount; } + } + } else { + for (int j = 0; j < code.get(i).definition.operands.length; j++) { + if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { + long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; + if (target > instruction.offset) { + code.get(i).operands[j] += byteCount; + } + if (target == instruction.offset && !preRefsToThis) { + code.get(i).operands[j] += byteCount; + } + } } } } } { for (int i = pos; i < code.size(); i++) { - for (int j = 0; j < code.get(i).definition.operands.length; j++) { - if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; + if (code.get(i).definition instanceof LookupSwitchIns) { + long target = code.get(i).offset + code.get(i).operands[0]; + if (target < instruction.offset) { + code.get(i).operands[0] -= byteCount; + } + if (target == instruction.offset && postRefsToThis) { + code.get(i).operands[0] -= byteCount; + } + for (int k = 2; k < code.get(i).operands.length; k++) { + target = code.get(i).offset + code.get(i).operands[k]; if (target < instruction.offset) { - code.get(i).operands[j] -= byteCount; + code.get(i).operands[k] -= byteCount; } if (target == instruction.offset && postRefsToThis) { - code.get(i).operands[j] -= byteCount; + code.get(i).operands[k] -= byteCount; + } + } + } else { + for (int j = 0; j < code.get(i).definition.operands.length; j++) { + if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { + long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; + if (target < instruction.offset) { + code.get(i).operands[j] -= byteCount; + } + if (target == instruction.offset && postRefsToThis) { + code.get(i).operands[j] -= byteCount; + } } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index c29e13c1c..eff50d8c5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -528,7 +528,7 @@ public class AVM2Graph extends Graph { GraphTargetItem nt = sstack.peek(); if (!(nt instanceof IntegerValueAVM2Item)) { - throw new RuntimeException("Invalid integer value in Switch"); + throw new RuntimeException("Invalid integer value in Switch:" + nt); } IntegerValueAVM2Item iv = (IntegerValueAVM2Item) nt; caseValuesMap.put((int) (long) iv.value, tar); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java index ce7c35d1a..8c75a60ad 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/IntegerValueAVM2Item.java @@ -49,7 +49,7 @@ public class IntegerValueAVM2Item extends NumberValueAVM2Item { @Override public Object getResult() { - return (Double) (double) (long) value; + return value;//(Double) (double) (long) value; } @Override From 18c295010abfe2864b0d86ee9fae52938ab58ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 21 Jun 2015 07:31:36 +0200 Subject: [PATCH 14/20] AS3: insert instruction fix for try --- .../decompiler/flash/abc/avm2/AVM2Code.java | 20 +++++++++++++++---- .../abc/avm2/AVM2DeobfuscatorSimple.java | 4 ++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 81324e6c7..ec330c9cc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1847,16 +1847,16 @@ public class AVM2Code implements Cloneable { * @param pos * @param instruction */ - public void insertInstruction(int pos, AVM2Instruction instruction) { - insertInstruction(pos, instruction, true, false); + public void insertInstruction(int pos, AVM2Instruction instruction, MethodBody body) { + insertInstruction(pos, instruction, true, false, body); } public void replaceInstruction(int idx, AVM2Instruction ins, MethodBody body) { - insertInstruction(idx, ins, true, true); + insertInstruction(idx, ins, true, true, body); removeInstruction(idx + 1, body); } - public void insertInstruction(int pos, AVM2Instruction instruction, boolean preRefsToThis, boolean postRefsToThis) { + public void insertInstruction(int pos, AVM2Instruction instruction, boolean preRefsToThis, boolean postRefsToThis, MethodBody body) { if (pos < 0) { pos = 0; } @@ -1870,6 +1870,18 @@ public class AVM2Code implements Cloneable { instruction.offset = code.get(pos).offset; } + for (ABCException ex : body.exceptions) { + if (ex.start > instruction.offset) { + ex.start += byteCount; + } + if (ex.end > instruction.offset) { + ex.end += byteCount; + } + if (ex.target > instruction.offset) { + ex.target += byteCount; + } + } + { for (int i = 0; i < pos; i++) { if (code.get(i).definition instanceof LookupSwitchIns) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java index bfeabfa67..9927570c4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java @@ -178,7 +178,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { } AVM2Instruction ins = makePush(graphTargetItem.getResult(), cpool); if (ins != null) { - code.insertInstruction(i + (idelta++), ins); + code.insertInstruction(i + (idelta++), ins, body); //prevAction = ins; } else { throw new TranslateException("Cannot push: " + graphTargetItem); @@ -188,7 +188,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { } AVM2Instruction jump = new AVM2Instruction(0, new JumpIns(), new int[]{0}); - code.insertInstruction(i + (idelta++), jump); + code.insertInstruction(i + (idelta++), jump, body); jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length)); From 1747d06edff9b0da2b1ec5748f397c54732a2abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 21 Jun 2015 14:40:00 +0200 Subject: [PATCH 15/20] AS3: Jump deobfuscation improved --- .../deobfuscation/AVM2DeobfuscatorJumps.java | 90 +++++++++++++++++++ .../AVM2DeobfuscatorRegisters.java | 11 +-- .../AVM2DeobfuscatorSimple.java | 19 +++- .../flash/abc/types/MethodBody.java | 11 ++- .../flash/abc/types/MethodInfo.java | 6 +- .../src/com/jpexs/decompiler/graph/Graph.java | 36 +++----- .../flash/ActionScript3DeobfuscatorTest.java | 60 +++++++++++++ 7 files changed, 194 insertions(+), 39 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/{ => deobfuscation}/AVM2DeobfuscatorRegisters.java (96%) rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/{ => deobfuscation}/AVM2DeobfuscatorSimple.java (94%) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java new file mode 100644 index 000000000..c90450130 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.deobfuscation; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.action.ActionList; +import java.util.List; +import java.util.Map; + +/** + * + * AVM2 Deobfuscator removing single assigned local registers. + * + * Example: var a = true; var b = false; ... if(a){ ...ok }else{ not executed } + * + * @author JPEXS + */ +public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple { + + //private final int executionLimit = 30000; + @Override + public void actionListParsed(ActionList actions, SWF swf) { + + } + + @Override + public void deobfuscate(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + + //body.getCode().markMappedOffsets(); + //removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + AVM2Code code = body.getCode(); + + boolean found; + do { + found = false; + Map> refs = body.getCode().visitCode(body); + loopi: + for (int i = 0; i < code.code.size(); i++) { + AVM2Instruction ins = code.code.get(i); + if (ins.definition instanceof JumpIns) { + long targetAddr = ins.offset + ins.operands[0] + ins.getBytes().length; + { + for (int r : refs.get(i)) { + if (r >= 0) { //Not Exception start/end + AVM2Instruction srcIns = code.code.get(r); + + if ((srcIns.definition instanceof JumpIns) || ((srcIns.definition instanceof IfTypeIns) && (r != i - 1))) { + { + int oldop = srcIns.operands[0]; + srcIns.operands[0] = (int) (targetAddr - (srcIns.offset + srcIns.getBytes().length)); + if (srcIns.operands[0] != oldop) { + found = true; + System.err.println("found"); + } + } + } + } + } + } + } + } + removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + } while (found); + + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorRegisters.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java similarity index 96% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorRegisters.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java index bf6005041..e4fe997cc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorRegisters.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java @@ -14,12 +14,14 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. */ -package com.jpexs.decompiler.flash.abc.avm2; +package com.jpexs.decompiler.flash.abc.avm2.deobfuscation; import com.jpexs.decompiler.flash.BaseLocalData; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2GraphSource; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; @@ -139,13 +141,6 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { AVM2Instruction action = code.code.get(idx); instructionsProcessed++; - - /*if (action.definition instanceof GetLocalTypeIns) { - int regId = ((GetLocalTypeIns) action.definition).getRegisterId(action);//stack.peek().getResult().toString(); - if (!localData.localRegs.containsKey(regId)) { - break; - } - }*/ action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); InstructionDefinition def = action.definition; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java similarity index 94% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java index 9927570c4..397c659a1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2DeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java @@ -14,11 +14,14 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. */ -package com.jpexs.decompiler.flash.abc.avm2; +package com.jpexs.decompiler.flash.abc.avm2.deobfuscation; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.FixItemCounterTranslateStack; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; @@ -37,6 +40,11 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; @@ -311,7 +319,14 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { EqualsIns.class, NotIns.class, IfTypeIns.class, - JumpIns.class + JumpIns.class, + EqualsIns.class, + LessEqualsIns.class, + GreaterEqualsIns.class, + GreaterThanIns.class, + LessThanIns.class, + StrictEqualsIns.class, + PopIns.class }; boolean ok = false; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 1af07b3d3..956c30efd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -20,10 +20,11 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ABCInputStream; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.AVM2DeobfuscatorRegisters; -import com.jpexs.decompiler.flash.abc.avm2.AVM2DeobfuscatorSimple; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorRegisters; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorSimple; import com.jpexs.decompiler.flash.abc.avm2.CodeStats; import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorJumps; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -203,7 +204,7 @@ public final class MethodBody implements Cloneable { if (exportMode != ScriptExportMode.AS) { getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer); } else { - //if (!path.contains("@")) { + //if (!path.contains("RemoveAllPopup")) { if (!Configuration.decompile.get()) { writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); return; @@ -247,7 +248,7 @@ public final class MethodBody implements Cloneable { if (exportMode != ScriptExportMode.AS) { getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer); } else { - //if (!path.contains("@")) { + //if (!path.contains("RemoveAllPopup")) { if (!Configuration.decompile.get()) { //writer.startMethod(this.method_info); writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); @@ -291,6 +292,8 @@ public final class MethodBody implements Cloneable { } else { new AVM2DeobfuscatorSimple().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b); new AVM2DeobfuscatorRegisters().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b); + new AVM2DeobfuscatorJumps().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java index 4003aa7a4..2090c8fbd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java @@ -49,7 +49,7 @@ public class MethodInfo { } } - public int[] param_types; + public int[] param_types = new int[]{}; public int ret_type; @@ -74,9 +74,9 @@ public class MethodInfo { public int flags; - public ValueKind[] optional; + public ValueKind[] optional = new ValueKind[0]; - public int[] paramNames; + public int[] paramNames = new int[0]; private MethodBody body; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index ad8d72a54..f0167585b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -431,11 +431,12 @@ public class Graph { TranslateStack stack = new TranslateStack(path); List loops = new ArrayList<>(); getLoops(localData, heads.get(0), loops, null); - /*System.out.println(""); + /*1 + System.err.println(""); for (Loop el : loops) { - System.out.println(el); + System..println(el); } - System.out.println("");*/ + System.err.println("");*/ getPrecontinues(path, localData, null, heads.get(0), allParts, loops, null); /*System.err.println(""); for (Loop el : loops) { @@ -1378,7 +1379,7 @@ public class Graph { } if (el.phase != 1) { if (debugMode) { - //System.err.println("ignoring loop "+el); + System.err.println("ignoring loop " + el); } continue; } @@ -1418,18 +1419,9 @@ public class Graph { if (currentLoop != null) { currentLoop.phase = 0; } - /*switch (part.stopPartType) { - case AND_OR: - part.setAndOrStack(stack); //Save stack for later use - break; - - case COMMONPART: - part.setCommonPartStack(stack); //Save stack for later use - break; - - case NONE: - break; - }*/ + if (debugMode) { + System.err.println("Stopped on part " + part); + } return ret; } @@ -1562,19 +1554,19 @@ public class Graph { List nps; nps = part.nextParts; + boolean isEmpty = nps.get(0) == nps.get(1); + GraphPart next = getCommonPart(localData, nps, loops); TranslateStack trueStack = (TranslateStack) stack.clone(); TranslateStack falseStack = (TranslateStack) stack.clone(); trueStack.clear(); falseStack.clear(); - /*int trueStackSizeBefore = trueStack.size(); - int falseStackSizeBefore = falseStack.size(); - */ - boolean isEmpty = nps.get(0) == nps.get(1); if (isEmpty) { next = nps.get(0); } + boolean hasOntrue = nps.get(1) != next; + boolean hasOnFalse = nps.get(0) != next; List stopPart2 = new ArrayList<>(stopPart); @@ -1583,12 +1575,12 @@ public class Graph { } List onTrue = new ArrayList<>(); - if (!isEmpty) { + if (!isEmpty && hasOntrue) { onTrue = printGraph(visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); } List onFalse = new ArrayList<>(); - if (!isEmpty) { + if (!isEmpty && hasOnFalse) { onFalse = printGraph(visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); } //List out2 = new ArrayList<>(); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java index ff5e33f9a..9e2facc15 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java @@ -17,9 +17,14 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorJumps; import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; +import com.jpexs.decompiler.flash.abc.avm2.parser.pcode.ASM3Parser; import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.CodeFormatting; @@ -29,8 +34,10 @@ import com.jpexs.decompiler.graph.CompilationException; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; +import java.io.StringReader; import java.util.ArrayList; import java.util.concurrent.TimeoutException; +import org.testng.Assert; import static org.testng.Assert.fail; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; @@ -50,6 +57,39 @@ public class ActionScript3DeobfuscatorTest extends ActionStript2TestBase { swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false); } + private String recompilePCode(String str) throws IOException, AVM2ParseException, InterruptedException { + str = "code\r\n" + + "getlocal_0\r\n" + + "pushscope\r\n" + + str + + "returnvoid\r\n"; + final ABC abc = new ABC(new ABCContainerTag() { + + @Override + public ABC getABC() { + return null; + } + + @Override + public SWF getSwf() { + return swf; + } + + @Override + public int compareTo(ABCContainerTag o) { + return 0; + } + }); + MethodBody b = new MethodBody(); + AVM2Code code = ASM3Parser.parse(new StringReader(str), abc.constants, null, b, new MethodInfo()); + b.setCode(code); + new AVM2DeobfuscatorJumps().deobfuscate("test", 0, true, 0, abc, abc.constants, null, new MethodInfo(), b); + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + code.toASMSource(abc.constants, null, new MethodInfo(), new MethodBody(), ScriptExportMode.PCODE, writer); + String ret = writer.toString(); + return ret.substring(ret.lastIndexOf("code\r\n") + 6); + } + private String recompile(String str) throws AVM2ParseException, IOException, CompilationException, InterruptedException { str = "package { public class Test { public static function trace(s){ } public static function test(){ " + str + " } } }"; final ABC abc = new ABC(new ABCContainerTag() { @@ -182,6 +222,26 @@ public class ActionScript3DeobfuscatorTest extends ActionStript2TestBase { } } + @Test + public void testJumps() throws Exception { + String res = recompilePCode("pushbyte 3\r\n" + + "pushbyte 4\r\n" + + "ifeq a\r\n" //should change to ifeq c + + "jump b\r\n" //should not change + + "a:jump c\r\n" + + "c:pushbyte 4\r\n" + + "b:pushbyte 3\r\n"); + Assert.assertEquals(res, "getlocal_0\r\n" + + "pushscope\r\n" + + "pushbyte 3\r\n" + + "pushbyte 4\r\n" + + "ifeq ofs000e\r\n" + + "jump ofs0010\r\n" + + "ofs000e:pushbyte 4\r\n" + + "ofs0010:pushbyte 3\r\n" + + "returnvoid\r\n"); + } + // TODO: JPEXS @Test public void testNotRemoveParams() throws Exception { String res = recompile("function tst(p1,p2){" From 108f86dd98d4e3ae29da36d769e3063307463dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 21 Jun 2015 14:45:14 +0200 Subject: [PATCH 16/20] Deobfuscation switch to old mode is now hidden in other configuration. System out fix --- .../deobfuscation/AVM2DeobfuscatorJumps.java | 1 - .../flash/configuration/Configuration.java | 2 +- .../decompiler/flash/gui/MainFrameMenu.java | 38 +++++++++---------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java index c90450130..827c0a93b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java @@ -73,7 +73,6 @@ public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple { srcIns.operands[0] = (int) (targetAddr - (srcIns.offset + srcIns.getBytes().length)); if (srcIns.operands[0] != oldop) { found = true; - System.err.println("found"); } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index a8fb6111d..eabd60c4b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -91,7 +91,7 @@ public class Configuration { public static final ConfigurationItem autoDeobfuscate = null; @ConfigurationDefaultInt(1) - @ConfigurationCategory("script") + @ConfigurationCategory("") public static final ConfigurationItem deobfuscationMode = null; @ConfigurationDefaultBoolean(false) diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index 3e2780c3e..8e73f5160 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -804,16 +804,15 @@ public abstract class MainFrameMenu implements MenuBuilder { addMenuItem("/settings/language/setLanguage", translate("menu.settings.language"), "setlanguage32", this::setLanguageActionPerformed, PRIORITY_TOP, null, true); finishMenu("/settings/language"); - addMenuItem("/settings/deobfuscation", translate("menu.deobfuscation"), null, null, 0, null, false); - addToggleMenuItem("/settings/deobfuscation/old", translate("menu.file.deobfuscation.old"), "deobfuscation", "deobfuscateold16", (ActionEvent e) -> { - deobfuscationMode(e, 0); - }, 0); - addToggleMenuItem("/settings/deobfuscation/new", translate("menu.file.deobfuscation.new"), "deobfuscation", "deobfuscatenew16", (ActionEvent e) -> { - deobfuscationMode(e, 1); - }, 0); - - finishMenu("/settings/deobfuscation"); - + /*addMenuItem("/settings/deobfuscation", translate("menu.deobfuscation"), null, null, 0, null, false); + addToggleMenuItem("/settings/deobfuscation/old", translate("menu.file.deobfuscation.old"), "deobfuscation", "deobfuscateold16", (ActionEvent e) -> { + deobfuscationMode(e, 0); + }, 0); + addToggleMenuItem("/settings/deobfuscation/new", translate("menu.file.deobfuscation.new"), "deobfuscation", "deobfuscatenew16", (ActionEvent e) -> { + deobfuscationMode(e, 1); + }, 0); + + finishMenu("/settings/deobfuscation");*/ addMenuItem("/settings/advancedSettings", translate("menu.advancedsettings.advancedsettings"), null, null, 0, null, false); addMenuItem("/settings/advancedSettings/advancedSettings", translate("menu.advancedsettings.advancedsettings"), "settings32", this::advancedSettingsActionPerformed, PRIORITY_TOP, null, true); addMenuItem("/settings/advancedSettings/clearRecentFiles", translate("menu.tools.otherTools.clearRecentFiles"), "clearrecent16", this::clearRecentFilesActionPerformed, PRIORITY_MEDIUM, null, true); @@ -860,16 +859,15 @@ public abstract class MainFrameMenu implements MenuBuilder { setMenuEnabled("/settings/internalViewer", false); } - int deobfuscationMode = Configuration.deobfuscationMode.get(); - switch (deobfuscationMode) { - case 0: - setGroupSelection("deobfuscation", "/settings/deobfuscation/old"); - break; - case 1: - setGroupSelection("deobfuscation", "/settings/deobfuscation/new"); - break; - } - + /*int deobfuscationMode = Configuration.deobfuscationMode.get(); + switch (deobfuscationMode) { + case 0: + setGroupSelection("deobfuscation", "/settings/deobfuscation/old"); + break; + case 1: + setGroupSelection("deobfuscation", "/settings/deobfuscation/new"); + break; + }*/ if (Platform.isWindows()) { setMenuChecked("/settings/associate", ContextMenuTools.isAddedToContextMenu()); } From e49362cf47d2bc4d522cc5bfe23448311af046db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 21 Jun 2015 15:42:24 +0200 Subject: [PATCH 17/20] AS3: Faster remove ignored without reparsing --- .../decompiler/flash/abc/avm2/AVM2Code.java | 30 +++---------------- .../AVM2DeobfuscatorRegisters.java | 2 +- 2 files changed, 5 insertions(+), 27 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index ec330c9cc..ba0a7769e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -2525,35 +2525,13 @@ public class AVM2Code implements Cloneable { //restoreControlFlowPass(constants, body, true); } - /*private void removeIgnored(MethodBody body) { - for (int rem = code.size() - 1; rem >= 0; rem--) { - if (code.get(rem).ignored) { - removeInstruction(rem, body); - } - } - }*/ public void removeIgnored(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException { - try { - List outputMap = new ArrayList<>(); - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - toASMSource(constants, trait, info, body, outputMap, ScriptExportMode.PCODE, writer); - String src = writer.toString(); - AVM2Code acode = ASM3Parser.parse(new StringReader(src), constants, trait, body, info); - for (int i = 0; i < acode.code.size(); i++) { - if (outputMap.size() > i) { - int tpos = outputMap.get(i); - if (tpos == -1) { - } else if (code.get(tpos).mappedOffset >= 0) { - acode.code.get(i).mappedOffset = code.get(tpos).mappedOffset; - } else { - acode.code.get(i).mappedOffset = pos2adr(tpos); - } - } + for (int i = 0; i < code.size(); i++) { + if (code.get(i).ignored) { + removeInstruction(i, body); + i--; } - this.code = acode.code; - } catch (IOException | AVM2ParseException ex) { } - invalidateCache(); } public int removeDeadCode(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java index e4fe997cc..e81433260 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java @@ -233,7 +233,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { } } } catch (EmptyStackException | TranslateException | InterruptedException ex) { - ex.printStackTrace(); + //ignore } } From 7983b0bd01d38163f593ece05f21d12c35baf62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 2 Jul 2015 06:31:12 +0200 Subject: [PATCH 18/20] =?UTF-8?q?Adding=20goto=20=C2=A7=C2=A7=20instructio?= =?UTF-8?q?n=20for=20unresolved=20jumps=20(FlashCC=20etc.)=20AS3:=20Add/re?= =?UTF-8?q?move=20instruction=20improvement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../decompiler/flash/abc/avm2/AVM2Code.java | 332 ++++++++++-------- .../flash/abc/avm2/OffsetUpdater.java | 28 ++ .../deobfuscation/AVM2DeobfuscatorSimple.java | 120 +++---- .../flash/abc/avm2/graph/AVM2Graph.java | 16 +- .../flash/abc/types/MethodBody.java | 4 +- .../decompiler/flash/action/ActionGraph.java | 11 +- .../src/com/jpexs/decompiler/graph/Graph.java | 59 ++-- .../decompiler/graph/model/GotoItem.java | 59 ++++ .../decompiler/graph/model/LabelItem.java | 69 ++++ 9 files changed, 444 insertions(+), 254 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/GotoItem.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LabelItem.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index ba0a7769e..4c259920b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1770,193 +1770,191 @@ public class AVM2Code implements Cloneable { return list; } + public void updateOffsets(OffsetUpdater updater, MethodBody body) { + for (AVM2Instruction ins : code) { + if (ins.definition instanceof LookupSwitchIns) { + long target = ins.offset + ins.operands[0]; + ins.operands[0] = updater.updateOperandOffset(target, ins.operands[0]); + for (int k = 2; k < ins.operands.length; k++) { + target = ins.offset + ins.operands[k]; + ins.operands[k] = updater.updateOperandOffset(target, ins.operands[k]); + } + } else { + /*for (int j = 0; j < ins.definition.operands.length; j++) { + if (ins.definition.operands[j] == AVM2Code.DAT_OFFSET) { + long target = ins.offset + ins.getBytes().length + ins.operands[j]; + ins.operands[j] = updater.updateOperandOffset(target, ins.operands[j]); + } + }*/ + //Faster, but not so universal + if ((ins.definition instanceof JumpIns) || (ins.definition instanceof IfTypeIns)) { + long target = ins.offset + ins.getBytes().length + ins.operands[0]; + ins.operands[0] = updater.updateOperandOffset(target, ins.operands[0]); + } + } + } + + for (ABCException ex : body.exceptions) { + ex.start = updater.updateOperandOffset(ex.start, ex.start); + ex.end = updater.updateOperandOffset(ex.end, ex.end); + ex.target = updater.updateOperandOffset(ex.target, ex.target); + } + for (AVM2Instruction ins : code) { + ins.offset = updater.updateInstructionOffset(ins.offset); + } + } + + private void checkValidOffsets(MethodBody body) { + updateOffsets(new OffsetUpdater() { + + @Override + public long updateInstructionOffset(long offset) { + adr2pos(offset); + return offset; + } + + @Override + public int updateOperandOffset(long targetAddress, int offset) { + adr2pos(targetAddress); + return offset; + } + + }, body); + } + public void removeInstruction(int pos, MethodBody body) { if ((pos < 0) || (pos >= code.size())) { throw new IndexOutOfBoundsException(); } - int byteCount = code.get(pos).getBytes().length; - long remOffset = code.get(pos).offset; - for (int i = pos + 1; i < code.size(); i++) { - code.get(i).offset -= byteCount; - } + //checkValidOffsets(body); + final long remOffset = code.get(pos).offset; + final int byteCount = code.get(pos).getBytes().length; + updateOffsets(new OffsetUpdater() { + @Override + public long updateInstructionOffset(long address) { + if (address > remOffset) { + return address - byteCount; + } + return address; + } - for (ABCException ex : body.exceptions) { - if (ex.start > remOffset) { - ex.start -= byteCount; + @Override + public int updateOperandOffset(long targetAddress, int offset) { + if (targetAddress > remOffset) { + return offset - byteCount; + } + return offset; } - if (ex.end > remOffset) { - ex.end -= byteCount; - } - if (ex.target > remOffset) { - ex.target -= byteCount; - } - } - - for (int i = 0; i < pos; i++) { - if (code.get(i).definition instanceof LookupSwitchIns) { - long target = code.get(i).offset + code.get(i).operands[0]; - if (target > remOffset) { - code.get(i).operands[0] -= byteCount; - } - for (int k = 2; k < code.get(i).operands.length; k++) { - target = code.get(i).offset + code.get(i).operands[k]; - if (target > remOffset) { - code.get(i).operands[k] -= byteCount; - } - } - } else { - for (int j = 0; j < code.get(i).definition.operands.length; j++) { - if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; - if (target > remOffset) { - code.get(i).operands[j] -= byteCount; - } - } - } - } - } - for (int i = pos + 1; i < code.size(); i++) { - if (code.get(i).definition instanceof LookupSwitchIns) { - long target = code.get(i).offset + code.get(i).operands[0]; - if (target < remOffset) { - code.get(i).operands[0] += byteCount; - } - for (int k = 2; k < code.get(i).operands.length; k++) { - target = code.get(i).offset + code.get(i).operands[k]; - if (target < remOffset) { - code.get(i).operands[k] += byteCount; - } - } - } else { - for (int j = 0; j < code.get(i).definition.operands.length; j++) { - if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; - if (target < remOffset) { - code.get(i).operands[j] += byteCount; - } - } - } - } - } - + }, body); code.remove(pos); invalidateCache(); + //checkValidOffsets(body); + //System.exit(0); + } /** - * @param pos - * @param instruction + * Inserts instuction at specified point. Handles offsets properly. Note: If + * newinstruction is jump, the offset operand must be handled properly by + * caller. All old jump offsets to pos are targeted before new instruction. + * + * @param pos Position in the list + * @param instruction Instruction False means before new instruction + * @param body Method body (used for try handling) */ public void insertInstruction(int pos, AVM2Instruction instruction, MethodBody body) { - insertInstruction(pos, instruction, true, false, body); + insertInstruction(pos, instruction, false, body); } - public void replaceInstruction(int idx, AVM2Instruction ins, MethodBody body) { - insertInstruction(idx, ins, true, true, body); - removeInstruction(idx + 1, body); - } - - public void insertInstruction(int pos, AVM2Instruction instruction, boolean preRefsToThis, boolean postRefsToThis, MethodBody body) { + /** + * Replaces instrunction by another. Properly handles offsets. Note: If + * newinstruction is jump, the offset operand must be handled properly by + * caller. + * + * @param pos + * @param instruction + * @param body + */ + public void replaceInstruction(int pos, AVM2Instruction instruction, MethodBody body) { if (pos < 0) { pos = 0; } if (pos > code.size()) { pos = code.size(); } - int byteCount = instruction.getBytes().length; + instruction.offset = code.get(pos).offset; + int oldByteCount = code.get(pos).getBytes().length; + int newByteCount = instruction.getBytes().length; + int byteDelta = newByteCount - oldByteCount; + + if (byteDelta != 0) { + updateOffsets(new OffsetUpdater() { + + @Override + public long updateInstructionOffset(long offset) { + if (offset > instruction.offset) { + return offset + byteDelta; + } + return offset; + } + + @Override + public int updateOperandOffset(long targetAddress, int offset) { + if (targetAddress > instruction.offset) { + return offset + byteDelta; + } + return offset; + } + }, body); + } + code.set(pos, instruction); + } + + /** + * Inserts instuction at specified point. Handles offsets properly. Note: If + * newinstruction is jump, the offset operand must be handled properly by + * caller. + * + * @param pos Position in the list + * @param instruction Instruction + * @param mapOffsetsAfterIns Map all jumps to the pos after new instruction? + * False means before new instruction + * @param body Method body (used for try handling) + */ + public void insertInstruction(int pos, AVM2Instruction instruction, boolean mapOffsetsAfterIns, MethodBody body) { + if (pos < 0) { + pos = 0; + } + if (pos > code.size()) { + pos = code.size(); + } + final int byteCount = instruction.getBytes().length; if (pos == code.size()) { instruction.offset = code.get(pos - 1).offset + code.get(pos - 1).getBytes().length; } else { instruction.offset = code.get(pos).offset; } + updateOffsets(new OffsetUpdater() { - for (ABCException ex : body.exceptions) { - if (ex.start > instruction.offset) { - ex.start += byteCount; - } - if (ex.end > instruction.offset) { - ex.end += byteCount; - } - if (ex.target > instruction.offset) { - ex.target += byteCount; - } - } - - { - for (int i = 0; i < pos; i++) { - if (code.get(i).definition instanceof LookupSwitchIns) { - long target = code.get(i).offset + code.get(i).operands[0]; - if (target > instruction.offset) { - code.get(i).operands[0] += byteCount; - } - if (target == instruction.offset && !preRefsToThis) { - code.get(i).operands[0] += byteCount; - } - for (int k = 2; k < code.get(i).operands.length; k++) { - target = code.get(i).offset + code.get(i).operands[k]; - if (target > instruction.offset) { - code.get(i).operands[k] += byteCount; - } - if (target == instruction.offset && !preRefsToThis) { - code.get(i).operands[k] += byteCount; - } - } - } else { - for (int j = 0; j < code.get(i).definition.operands.length; j++) { - if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; - if (target > instruction.offset) { - code.get(i).operands[j] += byteCount; - } - if (target == instruction.offset && !preRefsToThis) { - code.get(i).operands[j] += byteCount; - } - - } - } + @Override + public long updateInstructionOffset(long offset) { + if (offset >= instruction.offset) { + return offset + byteCount; } + return offset; } - } - { - for (int i = pos; i < code.size(); i++) { - if (code.get(i).definition instanceof LookupSwitchIns) { - long target = code.get(i).offset + code.get(i).operands[0]; - if (target < instruction.offset) { - code.get(i).operands[0] -= byteCount; - } - if (target == instruction.offset && postRefsToThis) { - code.get(i).operands[0] -= byteCount; - } - for (int k = 2; k < code.get(i).operands.length; k++) { - target = code.get(i).offset + code.get(i).operands[k]; - if (target < instruction.offset) { - code.get(i).operands[k] -= byteCount; - } - if (target == instruction.offset && postRefsToThis) { - code.get(i).operands[k] -= byteCount; - } - } - } else { - for (int j = 0; j < code.get(i).definition.operands.length; j++) { - if (code.get(i).definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = code.get(i).offset + code.get(i).getBytes().length + code.get(i).operands[j]; - if (target < instruction.offset) { - code.get(i).operands[j] -= byteCount; - } - if (target == instruction.offset && postRefsToThis) { - code.get(i).operands[j] -= byteCount; - } - } - } - } - } - } - for (int i = pos; i < code.size(); i++) { - code.get(i).offset += byteCount; - } + @Override + public int updateOperandOffset(long targetAddress, int offset) { + if ((targetAddress > instruction.offset) || (mapOffsetsAfterIns && (targetAddress == instruction.offset))) { + return offset + byteCount; + } + return offset; + } + }, body); code.add(pos, instruction); invalidateCache(); + checkValidOffsets(body); } @SuppressWarnings("unchecked") @@ -2524,6 +2522,30 @@ public class AVM2Code implements Cloneable { restoreControlFlowPass(constants, trait, info, body, false); //restoreControlFlowPass(constants, body, true); } + /* + public void removeIgnored(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException { + try { + List outputMap = new ArrayList<>(); + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); + toASMSource(constants, trait, info, body, outputMap, ScriptExportMode.PCODE, writer); + String src = writer.toString(); + AVM2Code acode = ASM3Parser.parse(new StringReader(src), constants, trait, body, info); + for (int i = 0; i < acode.code.size(); i++) { + if (outputMap.size() > i) { + int tpos = outputMap.get(i); + if (tpos == -1) { + } else if (code.get(tpos).mappedOffset >= 0) { + acode.code.get(i).mappedOffset = code.get(tpos).mappedOffset; + } else { + acode.code.get(i).mappedOffset = pos2adr(tpos); + } + } + } + this.code = acode.code; + } catch (IOException | AVM2ParseException ex) { + } + invalidateCache(); + }*/ public void removeIgnored(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException { for (int i = 0; i < code.size(); i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java new file mode 100644 index 000000000..66d4ecbe9 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +/** + * + * @author JPEXS + */ +public interface OffsetUpdater { + + public long updateInstructionOffset(long offset); + + public int updateOperandOffset(long targetAddress, int offset); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java index 397c659a1..8c0bfea1c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java @@ -164,67 +164,50 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { ExecutionResult result = new ExecutionResult(); executeActions(classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result); - if (result.idx != -1) { - int newIstructionCount = 1; // jump - if (!result.stack.isEmpty()) { - newIstructionCount += result.stack.size(); - } + /*if (result.idx != -1) { + int newIstructionCount = 1; // jump + if (!result.stack.isEmpty()) { + newIstructionCount += result.stack.size(); + } - if (newIstructionCount < result.instructionsProcessed) //if (result.isIf) - { - AVM2Instruction target = code.code.get(result.idx); - AVM2Instruction prevAction = code.code.get(i); - int idelta = 0; + if (newIstructionCount < result.instructionsProcessed) //if (result.isIf) + { + AVM2Instruction target = code.code.get(result.idx); + AVM2Instruction prevAction = code.code.get(i); + int idelta = 0; - if (result.stack.isEmpty() && prevAction.definition instanceof JumpIns) { - prevAction.operands[0] = ((int) (target.offset - prevAction.offset - prevAction.getBytes().length)); - } else { - if (!result.stack.isEmpty()) { - for (GraphTargetItem graphTargetItem : result.stack) { - if (graphTargetItem instanceof PopItem) { - continue; - } - AVM2Instruction ins = makePush(graphTargetItem.getResult(), cpool); - if (ins != null) { - code.insertInstruction(i + (idelta++), ins, body); - //prevAction = ins; - } else { - throw new TranslateException("Cannot push: " + graphTargetItem); - } + if (result.stack.isEmpty() && prevAction.definition instanceof JumpIns) { + prevAction.operands[0] = ((int) (target.offset - prevAction.offset - prevAction.getBytes().length)); + } else { + if (!result.stack.isEmpty()) { + for (GraphTargetItem graphTargetItem : result.stack) { + if (graphTargetItem instanceof PopItem) { + continue; + } + AVM2Instruction ins = makePush(graphTargetItem.getResult(), cpool); + if (ins != null) { + code.insertInstruction(i + (idelta++), ins, body); + //prevAction = ins; + } else { + throw new TranslateException("Cannot push: " + graphTargetItem); + } - } - } + } + } - AVM2Instruction jump = new AVM2Instruction(0, new JumpIns(), new int[]{0}); - code.insertInstruction(i + (idelta++), jump, body); + AVM2Instruction jump = new AVM2Instruction(0, new JumpIns(), new int[]{0}); + code.insertInstruction(i + (idelta++), jump, body); - jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length)); + jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length)); - } + } - removeUnreachableActions(code, cpool, trait, minfo, body); - removeZeroJumps(code, body); + removeUnreachableActions(code, cpool, trait, minfo, body); + removeZeroJumps(code, body); - i = -1; - /*if (nextAction != null) { - long mapped = nextAction.mappedOffset; - int nextIdx = -1; - for (int p = 0; p < code.code.size(); p++) { - if (code.code.get(p).mappedOffset == mapped) { - nextIdx = p; - break; - } - } - if (nextIdx == -1) { - //? - break; - } else { - i = nextIdx - 1; - } - - }*/ - } - } + i = -1; + } + }*/ } return false; @@ -340,7 +323,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { break; } - //boolean ifed = false; + boolean ifed = false; if (def instanceof JumpIns) { //ActionJump jump = (ActionJump) action; long address = action.offset + action.getBytes().length + action.operands[0]; @@ -353,18 +336,29 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { //ActionIf aif = (ActionIf) action; GraphTargetItem top = stack.pop(); Object res = top.getResult(); + long address = action.offset + action.getBytes().length + action.operands[0]; + int nidx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); + AVM2Instruction tarIns = code.code.get(nidx); + if (EcmaScript.toBoolean(res)) { - long address = action.offset + action.getBytes().length + action.operands[0]; - idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); - if (idx == -1) { - throw new TranslateException("If target not found: " + address); - } - //ifed = true; + /*if (nidx == -1) { + throw new TranslateException("If target not found: " + address); + }*/ + AVM2Instruction jumpIns = new AVM2Instruction(0, new JumpIns(), new int[]{0}); + //jumpIns.operands[0] = action.operands[0] /*- action.getBytes().length*/ + jumpIns.getBytes().length; + code.replaceInstruction(idx, jumpIns, body); + jumpIns.operands[0] = (int) (tarIns.offset - jumpIns.offset - jumpIns.getBytes().length); + + code.insertInstruction(idx, new AVM2Instruction(action.offset, new DeobfuscatePopIns(), new int[]{}), true, body); + + idx = code.adr2pos(jumpIns.offset + jumpIns.getBytes().length + jumpIns.operands[0]); } else { - //action.definition = new DeobfuscatePopIns(); code.replaceInstruction(idx, new AVM2Instruction(action.offset, new DeobfuscatePopIns(), new int[]{}), body); + //action.definition = new DeobfuscatePopIns(); idx++; } + ifed = true; + //break; } else { idx++; } @@ -377,7 +371,9 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { result.stack.clear(); result.stack.addAll(stack); } - + if (ifed) { + break; + } } } catch (EmptyStackException | TranslateException | InterruptedException ex) { //result.idx = -1; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index eff50d8c5..2d9a0c447 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -167,7 +167,7 @@ public class AVM2Graph extends Graph { } @Override - protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { + protected List check(Map> partCodes, Map partCodePos, GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { List ret = null; AVM2LocalData aLocalData = (AVM2LocalData) localData; @@ -277,7 +277,7 @@ public class AVM2Graph extends Graph { finallyJumps.clear(); ignoredSwitches.put(e, swPos); st.push(new PopItem(null)); - finallyCommands = printGraph(localData, st, allParts, parent, fpart, null, loops, staticOperation, path); + finallyCommands = printGraph(partCodes, partCodePos, localData, st, allParts, parent, fpart, null, loops, staticOperation, path); //ignoredSwitches.remove(igs_size-1); finallyJumps.putAll(oldFinallyJumps); if (!finallyJumps.containsKey(e)) { @@ -336,7 +336,7 @@ public class AVM2Graph extends Graph { stopPart2.add(retPart); } - List ncatchedCommands = printGraph(localData2, st2, allParts, parent, npart, stopPart2, loops, staticOperation, path); + List ncatchedCommands = printGraph(partCodes, partCodePos, localData2, st2, allParts, parent, npart, stopPart2, loops, staticOperation, path); if (catchedExceptions.get(e).isFinally() && (catchedExceptions.size() > 1 || hasFinally)) { catchedExceptions.remove(e); e--; @@ -376,7 +376,7 @@ public class AVM2Graph extends Graph { } TranslateStack st = (TranslateStack) stack.clone(); st.clear(); - List tryCommands = printGraph(localData, st, allParts, parent, part, stopPart2, loops, staticOperation, path); + List tryCommands = printGraph(partCodes, partCodePos, localData, st, allParts, parent, part, stopPart2, loops, staticOperation, path); if (retPart != null && avm2code.code.get(retPart.start).isExit() && !(!tryCommands.isEmpty() && (tryCommands.get(tryCommands.size() - 1) instanceof ExitItem))) { avm2code.code.get(retPart.start).translate(localData, st, tryCommands, staticOperation, path); } @@ -413,7 +413,7 @@ public class AVM2Graph extends Graph { TranslateStack st = (TranslateStack) stack.clone(); st.clear(); - ret.addAll(printGraph(localData, st, allParts, null, part, stopPart, loops, staticOperation, path)); + ret.addAll(printGraph(partCodes, partCodePos, localData, st, allParts, null, part, stopPart, loops, staticOperation, path)); } else { ret.add(lop); } @@ -603,7 +603,7 @@ public class AVM2Graph extends Graph { defaultPart = switchLoc.nextParts.get(switchLoc.nextParts.size() - 1); List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(next); - defaultCommands = printGraph(localData, stack, allParts, switchLoc, defaultPart, stopPart2, loops, staticOperation, path); + defaultCommands = printGraph(partCodes, partCodePos, localData, stack, allParts, switchLoc, defaultPart, stopPart2, loops, staticOperation, path); if (!defaultCommands.isEmpty()) { if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) { if (((BreakItem) defaultCommands.get(defaultCommands.size() - 1)).loopId == currentLoop.id) { @@ -630,7 +630,7 @@ public class AVM2Graph extends Graph { stopPart2.add(defaultPart); } - cc.addAll(0, printGraph(localData, stack, allParts, switchLoc, caseBodies.get(i), stopPart2, loops, staticOperation, path)); + cc.addAll(0, printGraph(partCodes, partCodePos, localData, stack, allParts, switchLoc, caseBodies.get(i), stopPart2, loops, staticOperation, path)); caseCommands.add(cc); } @@ -642,7 +642,7 @@ public class AVM2Graph extends Graph { ret.add(ti); } else {*/ currentLoop.phase = 2; - ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); + ret.addAll(printGraph(partCodes, partCodePos, localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); //} } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 956c30efd..5d4b0e288 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -204,7 +204,7 @@ public final class MethodBody implements Cloneable { if (exportMode != ScriptExportMode.AS) { getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer); } else { - //if (!path.contains("RemoveAllPopup")) { + //if (!path.contains("_addGarbageLineMulti")) { if (!Configuration.decompile.get()) { writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); return; @@ -248,7 +248,7 @@ public final class MethodBody implements Cloneable { if (exportMode != ScriptExportMode.AS) { getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer); } else { - //if (!path.contains("RemoveAllPopup")) { + //if (!path.contains("_addGarbageLineMulti")) { if (!Configuration.decompile.get()) { //writer.startMethod(this.method_info); writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java index 599018dc0..ffd4ef06f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -53,6 +53,7 @@ import com.jpexs.decompiler.graph.model.WhileItem; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @@ -247,7 +248,7 @@ public class ActionGraph extends Graph { } @Override - protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { + protected List check(Map> partCodes, Map partCodePos, GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { if (!output.isEmpty()) { if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { StoreRegisterActionItem str = (StoreRegisterActionItem) output.get(output.size() - 1); @@ -310,7 +311,7 @@ public class ActionGraph extends Graph { List defaultCommands = new ArrayList<>(); List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(defaultPart2); - defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path); + defaultCommands = printGraph(partCodes, partCodePos, localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path); List loopContinues = new ArrayList<>(); for (Loop l : loops) { @@ -384,7 +385,7 @@ public class ActionGraph extends Graph { if ((defaultPart != null) && (defaultCommands.isEmpty())) { List stopPart2x = new ArrayList<>(stopPart); stopPart2x.add(next); - defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path); + defaultCommands = printGraph(partCodes, partCodePos, localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path); } if (!defaultCommands.isEmpty()) { @@ -433,7 +434,7 @@ public class ActionGraph extends Graph { if (breakPart != null) { stopPart2x.add(breakPart); } - cc.addAll(0, printGraph(localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); + cc.addAll(0, printGraph(partCodes, partCodePos, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); if (cc.size() >= 2) { if (cc.get(cc.size() - 1) instanceof BreakItem) { if ((cc.get(cc.size() - 2) instanceof ContinueItem) || (cc.get(cc.size() - 2) instanceof BreakItem)) { @@ -452,7 +453,7 @@ public class ActionGraph extends Graph { if (ti != null) { ret.add(ti); } else { - ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); + ret.addAll(printGraph(partCodes, partCodePos, localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index f0167585b..7b255fe6a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -31,8 +31,10 @@ import com.jpexs.decompiler.graph.model.DuplicateItem; import com.jpexs.decompiler.graph.model.ExitItem; import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.ForItem; +import com.jpexs.decompiler.graph.model.GotoItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.IntegerValueItem; +import com.jpexs.decompiler.graph.model.LabelItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.LogicalOpItem; import com.jpexs.decompiler.graph.model.LoopItem; @@ -434,7 +436,7 @@ public class Graph { /*1 System.err.println(""); for (Loop el : loops) { - System..println(el); + System.err.println(el); } System.err.println("");*/ getPrecontinues(path, localData, null, heads.get(0), allParts, loops, null); @@ -444,7 +446,7 @@ public class Graph { } System.err.println("");//*/ - List ret = printGraph(localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path); + List ret = printGraph(new HashMap<>(), new HashMap<>(), localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path); processIfs(ret); finalProcessStack(stack, ret); finalProcessAll(ret, 0, new FinalProcessLocalData()); @@ -731,7 +733,7 @@ public class Graph { return false; } - protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { + protected List check(Map> partCodes, Map partCodePos, GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { return null; } @@ -807,9 +809,9 @@ public class Graph { list.remove(list.size() - 1); } - protected List printGraph(BaseLocalData localData, TranslateStack stack, List allParts, GraphPart parent, GraphPart part, List stopPart, List loops, int staticOperation, String path) throws InterruptedException { + protected List printGraph(Map> partCodes, Map partCodePos, BaseLocalData localData, TranslateStack stack, List allParts, GraphPart parent, GraphPart part, List stopPart, List loops, int staticOperation, String path) throws InterruptedException { List visited = new ArrayList<>(); - return printGraph(visited, localData, stack, allParts, parent, part, stopPart, loops, null, staticOperation, path, 0); + return printGraph(partCodes, partCodePos, visited, localData, stack, allParts, parent, part, stopPart, loops, null, staticOperation, path, 0); } protected GraphTargetItem checkLoop(LoopItem loopItem, BaseLocalData localData, List loops) { @@ -1305,7 +1307,7 @@ public class Graph { } } - protected List printGraph(List visited, BaseLocalData localData, TranslateStack stack, List allParts, GraphPart parent, GraphPart part, List stopPart, List loops, List ret, int staticOperation, String path, int recursionLevel) throws InterruptedException { + protected List printGraph(Map> partCodes, Map partCodePos, List visited, BaseLocalData localData, TranslateStack stack, List allParts, GraphPart parent, GraphPart part, List stopPart, List loops, List ret, int staticOperation, String path, int recursionLevel) throws InterruptedException { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); } @@ -1315,11 +1317,7 @@ public class Graph { if (recursionLevel > allParts.size() + 1) { throw new TranslateException("printGraph max recursion level reached."); } - if (visited.contains(part)) { - //return new ArrayList(); - } else { - visited.add(part); - } + if (ret == null) { ret = new ArrayList<>(); } @@ -1429,6 +1427,23 @@ public class Graph { ret.add(new ScriptEndItem()); return ret; } + + if (visited.contains(part)) { + String labelName = "addr" + part.start; + List firstCode = partCodes.get(part); + int firstCodePos = partCodePos.get(part); + if (firstCode.size() > firstCodePos && (firstCode.get(firstCodePos) instanceof LabelItem)) { + labelName = ((LabelItem) firstCode.get(firstCodePos)).labelName; + } else { + firstCode.add(firstCodePos, new LabelItem(null, labelName)); + } + ret.add(new GotoItem(null, labelName)); + return ret; + } else { + visited.add(part); + partCodes.put(part, ret); + partCodePos.put(part, ret.size()); + } List currentRet = ret; UniversalLoopItem loopItem = null; TranslateStack sPreLoop = stack; @@ -1466,7 +1481,7 @@ public class Graph { } if (parseNext) { - List retCheck = check(code, localData, allParts, stack, parent, part, stopPart, loops, output, currentLoop, staticOperation, path); + List retCheck = check(partCodes, partCodePos, code, localData, allParts, stack, parent, part, stopPart, loops, output, currentLoop, staticOperation, path); if (retCheck != null) { if (!retCheck.isEmpty()) { currentRet.addAll(retCheck); @@ -1524,7 +1539,7 @@ public class Graph { //int stackLenBefore = stack.size(); TranslateStack s2 = (TranslateStack) stack.clone(); s2.clear(); - List nextCommands = printGraph(visited, prepareBranchLocalData(localData), s2, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + List nextCommands = printGraph(partCodes, partCodePos, visited, prepareBranchLocalData(localData), s2, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); makeAllCommands(nextCommands, s2); if (first) { defaultCommands = nextCommands; @@ -1539,7 +1554,7 @@ public class Graph { currentRet.add(sw); swLoop.phase = 2; if (next != null) { - currentRet.addAll(printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); + currentRet.addAll(printGraph(partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); } } //else GraphPart nextOnePart = null; @@ -1576,12 +1591,12 @@ public class Graph { List onTrue = new ArrayList<>(); if (!isEmpty && hasOntrue) { - onTrue = printGraph(visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + onTrue = printGraph(partCodes, partCodePos, visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); } List onFalse = new ArrayList<>(); if (!isEmpty && hasOnFalse) { - onFalse = printGraph(visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + onFalse = printGraph(partCodes, partCodePos, visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, null, staticOperation, path, recursionLevel + 1); } //List out2 = new ArrayList<>(); //makeAllCommands(out2, stack); @@ -1625,7 +1640,7 @@ public class Graph { } //currentRet.addAll(out2); if (next != null) { - printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1); + printGraph(partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1); //currentRet.addAll(); } } @@ -1634,7 +1649,7 @@ public class Graph { nextOnePart = part.nextParts.get(0); } if (nextOnePart != null) { - printGraph(visited, localData, stack, allParts, part, part.nextParts.get(0), stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1); + printGraph(partCodes, partCodePos, visited, localData, stack, allParts, part, part.nextParts.get(0), stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1); } } @@ -1659,7 +1674,7 @@ public class Graph { stopContPart.add(currentLoop.loopContinue); GraphPart precoBackup = currentLoop.loopPreContinue; currentLoop.loopPreContinue = null; - loopItem.commands.addAll(printGraph(visited, localData, new TranslateStack(path), allParts, null, precoBackup, stopContPart, loops, null, staticOperation, path, recursionLevel + 1)); + loopItem.commands.addAll(printGraph(partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, precoBackup, stopContPart, loops, null, staticOperation, path, recursionLevel + 1)); } } @@ -1716,7 +1731,7 @@ public class Graph { currentLoop.loopPreContinue = null; List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(currentLoop.loopContinue); - finalComm = printGraph(visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + finalComm = printGraph(partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); currentLoop.loopPreContinue = backup; checkContinueAtTheEnd(finalComm, currentLoop); } @@ -1793,7 +1808,7 @@ public class Graph { currentLoop.loopPreContinue = null; List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(currentLoop.loopContinue); - List finalComm = printGraph(visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); + List finalComm = printGraph(partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1); currentLoop.loopPreContinue = backup; checkContinueAtTheEnd(finalComm, currentLoop); @@ -1843,7 +1858,7 @@ public class Graph { } if (currentLoop.loopBreak != null) { - ret.addAll(printGraph(visited, localData, sPreLoop, allParts, part, currentLoop.loopBreak, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); + ret.addAll(printGraph(partCodes, partCodePos, visited, localData, sPreLoop, allParts, part, currentLoop.loopBreak, stopPart, loops, null, staticOperation, path, recursionLevel + 1)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/GotoItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/GotoItem.java new file mode 100644 index 000000000..d2c0a312c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/GotoItem.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph.model; + +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TypeItem; + +/** + * + * @author JPEXS + */ +public class GotoItem extends GraphTargetItem { + + public String labelName; + + public GotoItem(GraphSourceItem src, String labelName) { + super(src, PRECEDENCE_PRIMARY); + this.labelName = labelName; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.append("§§goto(" + labelName + ")"); + return writer; + } + + @Override + public boolean hasReturnValue() { + return false; + } + + @Override + public GraphTargetItem returnType() { + return TypeItem.UNBOUNDED; + } + + @Override + public Object getResult() { + return null; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LabelItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LabelItem.java new file mode 100644 index 000000000..fa61ceafb --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LabelItem.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.graph.model; + +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TypeItem; + +/** + * + * @author JPEXS + */ +public class LabelItem extends GraphTargetItem { + + public String labelName; + + public LabelItem(GraphSourceItem src, String labelName) { + super(src, PRECEDENCE_PRIMARY); + this.labelName = labelName; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.append(labelName + ":"); + return writer; + } + + @Override + public boolean needsNewLine() { + return false; + } + + @Override + public boolean needsSemicolon() { + return false; + } + + @Override + public boolean hasReturnValue() { + return false; + } + + @Override + public GraphTargetItem returnType() { + return TypeItem.UNBOUNDED; + } + + @Override + public Object getResult() { + return null; + } + +} From bc59d4295748213e837563dedb307b189f304c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 3 Jul 2015 07:08:27 +0200 Subject: [PATCH 19/20] AS3: ASM instruction remove/replace/insert fix, test added --- .../decompiler/flash/abc/avm2/AVM2Code.java | 54 ++++--- .../flash/abc/avm2/OffsetUpdater.java | 4 +- .../flash/ActionScript3AssemblerTest.java | 148 ++++++++++++++++++ 3 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3AssemblerTest.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 4c259920b..aadf42769 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1771,13 +1771,14 @@ public class AVM2Code implements Cloneable { } public void updateOffsets(OffsetUpdater updater, MethodBody body) { - for (AVM2Instruction ins : code) { + for (int i = 0; i < code.size(); i++) { + AVM2Instruction ins = code.get(i); if (ins.definition instanceof LookupSwitchIns) { long target = ins.offset + ins.operands[0]; - ins.operands[0] = updater.updateOperandOffset(target, ins.operands[0]); + ins.operands[0] = updater.updateOperandOffset(ins.offset, target, ins.operands[0]); for (int k = 2; k < ins.operands.length; k++) { target = ins.offset + ins.operands[k]; - ins.operands[k] = updater.updateOperandOffset(target, ins.operands[k]); + ins.operands[k] = updater.updateOperandOffset(ins.offset, target, ins.operands[k]); } } else { /*for (int j = 0; j < ins.definition.operands.length; j++) { @@ -1789,18 +1790,16 @@ public class AVM2Code implements Cloneable { //Faster, but not so universal if ((ins.definition instanceof JumpIns) || (ins.definition instanceof IfTypeIns)) { long target = ins.offset + ins.getBytes().length + ins.operands[0]; - ins.operands[0] = updater.updateOperandOffset(target, ins.operands[0]); + ins.operands[0] = updater.updateOperandOffset(ins.offset, target, ins.operands[0]); } } + ins.offset = updater.updateInstructionOffset(ins.offset); } for (ABCException ex : body.exceptions) { - ex.start = updater.updateOperandOffset(ex.start, ex.start); - ex.end = updater.updateOperandOffset(ex.end, ex.end); - ex.target = updater.updateOperandOffset(ex.target, ex.target); - } - for (AVM2Instruction ins : code) { - ins.offset = updater.updateInstructionOffset(ins.offset); + ex.start = updater.updateOperandOffset(-1, ex.start, ex.start); + ex.end = updater.updateOperandOffset(-1, ex.end, ex.end); + ex.target = updater.updateOperandOffset(-1, ex.target, ex.target); } } @@ -1814,7 +1813,7 @@ public class AVM2Code implements Cloneable { } @Override - public int updateOperandOffset(long targetAddress, int offset) { + public int updateOperandOffset(long insAddr, long targetAddress, int offset) { adr2pos(targetAddress); return offset; } @@ -1826,7 +1825,7 @@ public class AVM2Code implements Cloneable { if ((pos < 0) || (pos >= code.size())) { throw new IndexOutOfBoundsException(); } - //checkValidOffsets(body); + checkValidOffsets(body); final long remOffset = code.get(pos).offset; final int byteCount = code.get(pos).getBytes().length; updateOffsets(new OffsetUpdater() { @@ -1839,8 +1838,11 @@ public class AVM2Code implements Cloneable { } @Override - public int updateOperandOffset(long targetAddress, int offset) { + public int updateOperandOffset(long insAddr, long targetAddress, int offset) { if (targetAddress > remOffset) { + if (insAddr > remOffset) { + return offset; + } return offset - byteCount; } return offset; @@ -1848,7 +1850,7 @@ public class AVM2Code implements Cloneable { }, body); code.remove(pos); invalidateCache(); - //checkValidOffsets(body); + checkValidOffsets(body); //System.exit(0); } @@ -1891,23 +1893,28 @@ public class AVM2Code implements Cloneable { updateOffsets(new OffsetUpdater() { @Override - public long updateInstructionOffset(long offset) { - if (offset > instruction.offset) { - return offset + byteDelta; + public long updateInstructionOffset(long addr) { + if (addr > instruction.offset) { + return addr + byteDelta; } - return offset; + return addr; } @Override - public int updateOperandOffset(long targetAddress, int offset) { - if (targetAddress > instruction.offset) { + public int updateOperandOffset(long insAddr, long targetAddress, int offset) { + if (targetAddress > instruction.offset && insAddr <= instruction.offset) { return offset + byteDelta; } + if (targetAddress <= instruction.offset && insAddr > instruction.offset) { + return offset - byteDelta; + } return offset; } }, body); } code.set(pos, instruction); + invalidateCache(); + checkValidOffsets(body); } /** @@ -1922,6 +1929,7 @@ public class AVM2Code implements Cloneable { * @param body Method body (used for try handling) */ public void insertInstruction(int pos, AVM2Instruction instruction, boolean mapOffsetsAfterIns, MethodBody body) { + checkValidOffsets(body); if (pos < 0) { pos = 0; } @@ -1945,8 +1953,12 @@ public class AVM2Code implements Cloneable { } @Override - public int updateOperandOffset(long targetAddress, int offset) { + public int updateOperandOffset(long insAddr, long targetAddress, int offset) { + //System.err.println("instruction.offset=" + instruction.offset); if ((targetAddress > instruction.offset) || (mapOffsetsAfterIns && (targetAddress == instruction.offset))) { + if (insAddr >= instruction.offset) { + return offset; + } return offset + byteCount; } return offset; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java index 66d4ecbe9..33ea22753 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java @@ -22,7 +22,7 @@ package com.jpexs.decompiler.flash.abc.avm2; */ public interface OffsetUpdater { - public long updateInstructionOffset(long offset); + public long updateInstructionOffset(long addr); - public int updateOperandOffset(long targetAddress, int offset); + public int updateOperandOffset(long jumpAddr, long targetAddress, int offset); } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3AssemblerTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3AssemblerTest.java new file mode 100644 index 000000000..903fc4da9 --- /dev/null +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3AssemblerTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2010-2015 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorJumps; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; +import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; +import com.jpexs.decompiler.flash.abc.avm2.parser.pcode.ASM3Parser; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.flash.tags.DoABCDefineTag; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.StringReader; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript3AssemblerTest extends ActionScriptTestBase { + + private SWF swf; + + @BeforeClass + public void init() throws IOException, InterruptedException { + //Main.initLogging(false); + Configuration.autoDeobfuscate.set(true); + Configuration.deobfuscationMode.set(1); + swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false); + } + + private int getBaseAddr() { + return 2; //getlocal_0 + pushscope + } + + private ABC getABC() { + return new ABC(new ABCContainerTag() { + + @Override + public ABC getABC() { + return null; + } + + @Override + public SWF getSwf() { + return swf; + } + + @Override + public int compareTo(ABCContainerTag o) { + return 0; + } + }); + } + + private MethodBody compilePCode(String str) throws IOException, AVM2ParseException, InterruptedException { + str = "code\r\n" + + "getlocal_0\r\n" + + "pushscope\r\n" + + str + + "returnvoid\r\n"; + + MethodBody b = new MethodBody(); + AVM2Code code = ASM3Parser.parse(new StringReader(str), getABC().constants, null, b, new MethodInfo()); + b.setCode(code); + return b; + } + + /*private String codeToStr(AVM2Code code) { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + code.toASMSource(getABC().constants, null, new MethodInfo(), new MethodBody(), ScriptExportMode.PCODE, writer); + String ret = writer.toString(); + return ret.substring(ret.lastIndexOf("code\r\n") + 6); + }*/ + @Test + public void removeInstruction() throws Exception { + MethodBody b = compilePCode("pushbyte 1\r\n" + + "setlocal_1\r\n" //remove this + + "jump label1\r\n" + + "pushtrue\r\n" + + "pop\r\n" + + "label1:pushfalse\r\n"); + b.getCode().removeInstruction(getBaseAddr() + 1, b); + } + + @Test + public void removeInstruction2() throws Exception { + MethodBody b = compilePCode("pushbyte 1\r\n" + + "setlocal_1\r\n" + + "jump label1\r\n" + + "pushtrue\r\n" + + "pop\r\n" //remove this + + "label1:pushfalse\r\n"); + b.getCode().removeInstruction(getBaseAddr() + 4, b); + } + + @Test + public void replaceIstruction() throws Exception { + MethodBody b = compilePCode("pushbyte 1\r\n" + + "setlocal_1\r\n" + + "jump label1\r\n" //remove this + + "jump label1\r\n" + + "pushtrue\r\n" + + "pop\r\n" + + "label1:pushfalse\r\n"); + b.getCode().replaceInstruction(getBaseAddr() + 2, new AVM2Instruction(0, new DeobfuscatePopIns(), new int[]{}), b); + } + + @Test + public void replaceIstruction2() throws Exception { + MethodBody b = compilePCode("pushbyte 1\r\n" + + "setlocal_1\r\n" + + "jump label1\r\n" + + "pushtrue\r\n" + + "jump label1\r\n" //remove this + + "pop\r\n" + + "label1:pushfalse\r\n"); + b.getCode().replaceInstruction(getBaseAddr() + 4, new AVM2Instruction(0, new DeobfuscatePopIns(), new int[]{}), b); + } +} From ab5e79632b335eceac26f3f5606a3817fd00ab21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 3 Jul 2015 17:24:32 +0200 Subject: [PATCH 20/20] AS3 loop break fixed - tests now pass --- libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 7b255fe6a..6eb47253a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -1700,7 +1700,10 @@ public class Graph { } else if (loopItem.commands.size() == 2 && (loopItem.commands.get(1) instanceof BreakItem)) { BreakItem bi = (BreakItem) loopItem.commands.get(1); if (bi.loopId == currentLoop.id) { - bodyBranch = ifi.onTrue; + if (ifi.onTrue.isEmpty()) { + inverted = true; + } + bodyBranch = inverted ? ifi.onFalse : ifi.onTrue; breakpos2 = true; } }