Source code: jreversepro/revengine/JBranchEntry.java
1 /**
2 * @(#)JBranchEntry.java
3 *
4 *
5 * JReversePro - Java Decompiler / Disassembler.
6 * Copyright (C) 2000 2001 Karthik Kumar.
7 * EMail: akkumar@users.sourceforge.net
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it , under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License,
12 * or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program.If not, write to
20 * The Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
23 **/
24 package jreversepro.revengine;
25
26 import jreversepro.common.KeyWords;
27 import jreversepro.common.Helper;
28
29 import jreversepro.reflect.JMethod;
30 import jreversepro.reflect.JInstruction;
31
32 import jreversepro.reflect.method.JBlockObject;
33 import jreversepro.reflect.method.JIfBlock;
34 import jreversepro.reflect.method.JElseIfBlock;
35 import jreversepro.reflect.method.JElseBlock;
36 import jreversepro.reflect.method.JForBlock;
37 import jreversepro.reflect.method.JDoWhileBlock;
38 import jreversepro.reflect.method.JTryBlock;
39 import jreversepro.reflect.method.JFinallyBlock;
40 import jreversepro.reflect.method.JCatchBlock;
41 import jreversepro.reflect.method.JSynchBlock;
42 import jreversepro.reflect.method.JCaseBlock;
43 import jreversepro.reflect.method.JSwitchBlock;
44
45
46 import jreversepro.runtime.JOperandStack;
47 import jreversepro.runtime.Operand;
48 import jreversepro.runtime.OperandConstants;
49
50 /**
51 * JBranchEntry refers to a single conditional BranchEntry only.
52 * @author Karthik Kumar
53 **/
54 public class JBranchEntry implements KeyWords,
55 BranchConstants,
56 OperandConstants {
57
58 /**
59 * startPc is the start of the branch entry
60 **/
61 int startPc;
62
63 /**
64 * targetPc is the targetPc of the branch entry
65 **/
66 int targetPc;
67
68 /**
69 * nextPc is the NextPc of the branch entry.
70 **/
71 int nextPc;
72
73 /**
74 * type of the branch type
75 **/
76 int type;
77 //Possible values. TYPE_WHILE || TYPE_IF.
78
79 /**
80 * Operand 1
81 **/
82 String opr1;
83
84 /**
85 * Operand 2.
86 **/
87 String opr2;
88
89 /**
90 * Operator
91 **/
92 String operator;
93
94 /**
95 * Written flag - to signify if the branch has been written on the source
96 * code.
97 **/
98 boolean written;
99
100 /**
101 * The method corresponding to the code being processed
102 */
103 JMethod method;
104
105 /**
106 * The JBlockObject associated with this JBranchEntry
107 */
108 JBlockObject block = null;
109
110
111 /**
112 * @param method Method to which this branch entry belongs to.
113 * @param startPc StartPc
114 * @param targetPc TargetPc
115 * @param type Type of the branch
116 **/
117 public JBranchEntry(JMethod method,
118 int startPc, int targetPc, int type) {
119 this(method, startPc, startPc, targetPc, type, "", "", "");
120 if (type == TYPE_JSR) {
121 startPc = targetPc;
122 }
123 written = false;
124 }
125
126
127 /**
128 * @param method Method to which this branch entry belongs to.
129 * @param startPc StartPc
130 * @param nextPc NextPc
131 * @param targetPc TargetPc
132 * @param type Type of the branch
133 * @param opr1 Operand 1
134 * @param opr2 Operand 2
135 * @param operator Operator Comparison of the branch.
136 **/
137 public JBranchEntry(JMethod method,
138 int startPc, int nextPc, int targetPc,
139 int type, String opr1, String opr2,
140 String operator) {
141
142 this.method = method;
143
144 this.startPc = startPc;
145 this.nextPc = nextPc;
146 this.targetPc = targetPc;
147
148
149 this.type = type;
150
151 this.opr1 = opr1;
152 this.opr2 = opr2;
153 this.operator = operator;
154 }
155
156 /**
157 * Sets the written flag.
158 **/
159 public void setWrittenFlag() {
160 written = true;
161 }
162
163 /**
164 * Resets the written flag
165 **/
166 public void resetWrittenFlag() {
167 written = false;
168 }
169
170 /**
171 * Returns if the branch mentioned can be a TYPE_WHILE.
172 * One indication of a while loop is that the startPc > targetPc.
173 * @return true, if it is a while loop. false, otherwise.
174 **/
175 public boolean isWhile() {
176 return (startPc > targetPc);
177 }
178
179 /**
180 * @return Returns the startPc
181 **/
182 public int getStartPc() {
183 return startPc;
184 }
185
186 /**
187 * @return Returns the targetPc.
188 **/
189 public int getTargetPc() {
190 return targetPc;
191 }
192
193 /**
194 * @return Returns the NextPc.
195 **/
196 public int getNextPc() {
197 return nextPc;
198 }
199
200 /**
201 * @return Returns the type of the Branch.
202 **/
203 public final int getType() {
204 return type;
205 }
206
207 /**
208 * @return Returns the operand 1.
209 **/
210 public String getOpr1() {
211 return opr1;
212 }
213
214 /**
215 * Setter method for NextPc.
216 * @param nextPc Value for the nextPc.
217 **/
218 public void setNextPc(int nextPc) {
219 this.nextPc = nextPc;
220 }
221
222 /**
223 * @param targetPc TargetPC of the block.
224 **/
225 public void setTargetPc(int targetPc) {
226 this.targetPc = targetPc;
227 }
228
229 /**
230 * @param startPc StartPc of the branch.
231 * Setter method for startPc.
232 **/
233 public void setStartPc(int startPc) {
234 this.startPc = startPc;
235 }
236
237 /**
238 * Setter method for type.
239 * @param type Type of the branch.
240 **/
241 public void setType(int type) {
242 this.type = type;
243 }
244
245 /**
246 * @param opr1 Operand 1.
247 * Setter method for operand 1.
248 **/
249 public void setOpr1(String opr1) {
250 this.opr1 = opr1;
251 }
252
253 /**
254 * @param opr2 Operand 2.
255 * Setter method for operand 2.
256 **/
257 public void setOpr2(String opr2) {
258 this.opr2 = opr2;
259 }
260
261 /**
262 * This is invoked under the following circumstances. First this
263 * is recognized as a 'if' branch. Then afterwards recognized as
264 * 'while' branch.
265 **/
266 public void convertToWhile() {
267 this.type = TYPE_WHILE;
268
269 //Swap targetPc and NextPc.
270 int temp = targetPc;
271 targetPc = nextPc;
272 nextPc = temp;
273 }
274
275 /**
276 * Complements the conditional operator of the branch
277 **/
278 public void complementOperator() {
279 operator = getComplementOperator(operator);
280 }
281
282 /**
283 * Case 1:
284 * <p><br><code>
285 * a: x y z <br>
286 * b: y p1 p2 <br>
287 * z: <br><br></code>
288 * This means either a 'IF OR ' or and 'WHILE AND' between the
289 * statements.
290 * <br>
291 * Now the row 'b' is invalidated , and contents of a become
292 * <code><br>a: x p1 p2 <br></code>
293 * The Operands are also changed accordingly.
294 *
295 * Case 2:
296 * <p><br><code>
297 * a: x y z <br>
298 * b: y p1 z OR <br>
299 *
300 * a: x y z <br>
301 * z: ..... <br>
302 * b: y p1 p2 <br><br></code>
303 * This means either a 'IF AND' or 'WHILE OR' between the
304 * statements.<br>+
305 * Now the row 'b' is invalidated , and contents of a become
306 * <code><br>a: x p1 p2 <br></code>
307 * The Operands are also changed accordingly.
308 * <br></p>
309
310 * <br></p>
311 * @param case1 Merge case either case1 or case 2
312 * as mentioned above.
313 * @param ifstat If we have to write a if statements.
314 * @param entryB Other entry index for which we have to write the statement.
315 *
316 **/
317 void writeCase(boolean case1,
318 boolean ifstat, JBranchEntry entryB) {
319 this.type = entryB.type;
320 entryB.type = TYPE_INVALID;
321 //Invalidate entryB since that is irrelevant
322 //after merging.
323
324 this.nextPc = entryB.nextPc;
325 this.targetPc = entryB.targetPc;
326
327 this.rewriteCondition(entryB,
328 (ifstat ^ case1) ? COND_AND : COND_OR,
329 ifstat);
330
331
332 }
333
334 /**
335 * Collates a single statement , depending on if it is
336 * a IF / WHILE statement.
337 * <p></p>
338 * @return true , if the entry is a 'if' branch .
339 * false , otherwise.
340 *
341 **/
342 boolean collate() {
343 if (type == TYPE_JSR) {
344 return true;
345 }
346 if (startPc < targetPc) {
347 complementOperator();
348 return true;
349 } else {
350 if (type != TYPE_WHILE) {
351 type = TYPE_DO_WHILE;
352 }
353 return false;
354 }
355 }
356
357 /**
358 * This method checks if this particular branch block starts with
359 * the given Pc.
360 * @param rhsStartPc StartPc that is to be checked if a block
361 * starts there.
362 * @throws RevEngineException Thrown when any error occurs.
363 * @return true, if this block starts with the mentioned startPc.
364 * false, otherwise.
365 **/
366 public boolean doesStartWith(int rhsStartPc)
367 throws RevEngineException {
368
369 if (type == TYPE_INVALID) {
370 return false;
371 }
372 return (getStartBlockPc() == rhsStartPc);
373 }
374
375 /**
376 * Lets us know if the block is independent.
377 * When we say independent, we refer to blocks that can start on its own,
378 * Examples of the same - if, while, try, do..while. switch
379 * Examples of dependent branch blocks are .
380 * else_if , else, catch each dependent on one of the independent block
381 * for is existence
382 * @return true, if the block is independent.
383 * false, otherwise.
384 **/
385 public boolean independent() {
386 return type == TYPE_IF || type == TYPE_WHILE
387 || type == TYPE_TRY || type == TYPE_DO_WHILE
388 || type == TYPE_SYNC || type == TYPE_SWITCH
389 || type == TYPE_CASE || type == TYPE_TRY_ANY;
390 }
391
392 /**
393 * Returns if the given Pc is enclosed in the mentioned block
394 * @param aPc the Pc for which the location is to be mentioned.
395 * @return true, if the block mentioned contains this Pc.
396 * false, otherwise.
397 * @throws RevEngineException Thrown in case any error occurs while
398 * performing this operation.
399 **/
400 public boolean doesContain (int aPc)
401 throws RevEngineException {
402
403 return (getStartBlockPc() <= aPc
404 && getEndBlockPc() >= aPc);
405 }
406
407 /**
408 * @return Returns the start pc of this block.
409 * @throws RevEngineException Thrown in case of any error while geting
410 * start block Pc.
411 **/
412 public int getStartBlockPc()
413 throws RevEngineException {
414
415 switch(type) {
416 case TYPE_IF:
417 case TYPE_ELSE:
418 case TYPE_ELSE_IF:
419 case TYPE_TRY:
420 case TYPE_TRY_ANY:
421 case TYPE_CATCH:
422 case TYPE_CATCH_ANY:
423 case TYPE_JSR:
424 case TYPE_SYNC:
425 case TYPE_SWITCH:
426 case TYPE_CASE:
427 return startPc;
428 case TYPE_WHILE:
429 case TYPE_DO_WHILE:
430 return targetPc;
431 default:
432 throw new RevEngineException("Invalid Branch Entry");
433 }
434 }
435
436 /**
437 * @return Returns the endpc of the block under consideration.
438 * @throws RevEngineException Thrown in case there of any
439 * problem getting End block pc.
440 **/
441 public int getEndBlockPc()
442 throws RevEngineException {
443
444 switch(type) {
445 case TYPE_IF:
446 case TYPE_ELSE:
447 case TYPE_ELSE_IF:
448 case TYPE_TRY:
449 case TYPE_TRY_ANY:
450 case TYPE_CATCH:
451 case TYPE_CATCH_ANY:
452 case TYPE_JSR:
453 case TYPE_SYNC:
454 case TYPE_CASE:
455 case TYPE_SWITCH:
456 return targetPc;
457 case TYPE_WHILE:
458 case TYPE_DO_WHILE:
459 return nextPc;
460 default:
461 throw new RevEngineException("Invalid Branch Entry ");
462 }
463 }
464
465 /**
466 * @return Returns the Pc from which the execution for the
467 * block under consideration.
468 * @throws RevEngineException Thrown in case any error occurs.
469 **/
470 public int getStartExecPc()
471 throws RevEngineException {
472 switch (type) {
473 case TYPE_IF:
474 case TYPE_ELSE:
475 case TYPE_ELSE_IF:
476 case TYPE_TRY:
477 case TYPE_TRY_ANY:
478 case TYPE_CATCH:
479 case TYPE_CATCH_ANY:
480 case TYPE_JSR:
481 case TYPE_SYNC:
482 case TYPE_CASE:
483 case TYPE_SWITCH:
484 return nextPc;
485 case TYPE_WHILE:
486 case TYPE_DO_WHILE:
487 return targetPc;
488 default:
489 throw new RevEngineException("Invalid Branch Entry");
490 }
491 }
492
493 /**
494 * Append the code for the beginning of a block
495 * @param decomp Reference to decempiler.
496 **/
497 public final void appendStartBlockStmtX(JDecompiler decomp) {
498 JInstruction sIns = null;
499
500
501 Helper.log("Branch Begins " + this);
502 if (!(type == TYPE_CATCH_ANY
503 || type == TYPE_TRY_ANY)) {
504 switch (type) {
505 case TYPE_IF:
506 String expr = getExpression();
507 decomp.setLastIns(nextPc);
508 decomp.setLastInsPos(
509 method.getInstruction(nextPc).position);
510 method.addBlock(new JIfBlock(this, expr));
511 break;
512 case TYPE_ELSE_IF:
513 decomp.setLastIns(nextPc);
514 decomp.setLastInsPos(
515 method.getInstruction(nextPc).position);
516 method.addBlock(new JElseIfBlock(this, getExpression()));
517 break;
518 case TYPE_ELSE :
519 decomp.setLastIns(nextPc);
520 decomp.setLastInsPos(
521 method.getInstruction(nextPc).position);
522 method.addBlock(new JElseBlock(this));
523 break;
524 case TYPE_WHILE:
525 //This is a For loop
526 //Create a reference so we can add the missing init
527 //& loop values later
528 block = new JForBlock(this, getExpression());
529 method.addBlock(block);
530 //Set next pc to be after the end of the for loop
531 decomp.setLastIns(this.nextPc);
532 //decomp.setLastInsPos(this.?);
533 break;
534 case TYPE_DO_WHILE:
535 //Create a reference so we can add the operators later
536 block = new JDoWhileBlock(this);
537 method.addBlock(block);
538 break;
539 case TYPE_TRY:
540 method.addBlock(new JTryBlock(this));
541 break;
542 case TYPE_CATCH:
543 //Adjust start PC for executable instruction
544 //Set to next instruction
545 sIns = method.getNextInstruction(startPc);
546 decomp.setLastIns(sIns.index);
547 decomp.setLastInsPos(sIns.position);
548 method.addBlock(new JCatchBlock(this, opr1, opr2));
549 break;
550 case TYPE_JSR:
551 method.addBlock(new JFinallyBlock(this));
552 break;
553 case TYPE_SYNC:
554 method.addBlock(new JSynchBlock(this, opr1));
555 break;
556 case TYPE_CASE:
557 Helper.log("CASE BLOCK : " + opr1);
558 method.addBlock(new JCaseBlock(this, opr1));
559 break;
560 case TYPE_SWITCH:
561 method.addBlock(new JSwitchBlock(this, opr1));
562 break;
563 default:
564 }
565 }
566 }
567
568
569 /**
570 * Appends end block statement for a branch entry.
571 * @param decomp Decompiler reference.
572 * @param jos Java Operand Stack reference.
573 * @return Returns boolean.
574 **/
575 public final boolean appendEndBlockStmt(
576 JDecompiler decomp,
577 JOperandStack jos) {
578 boolean mergeStack = false;
579 if (!(type == TYPE_CATCH_ANY
580 || type == TYPE_TRY_ANY)) {
581 Helper.log("Branch Ends " + this);
582 switch (type) {
583 case TYPE_IF:
584 if (written) {
585 method.closeBlock();
586 decomp.setLastIns(nextPc);
587 //Set the index ptr to the ins after the end of
588 //this block
589 //JInstruction sIns =
590 // method.getInstruction(TargetPc);
591 //decomp.setLastIns(sIns.getTargetPc2());
592 //decomp.setLastInsPos(
593 // method.getInstruction(
594 // sIns.getTargetPc2()).position);
595 //
596 //System.out.println(
597 // "End sync - setting end to: "+sIns.getTargetPc());
598
599 //decomp.setLastInsPos(?);
600 } else if (!jos.empty()) {
601 //Rollback (remove current IF block)
602 method.removeCurrentBlock();
603 Operand op1 = (Operand) jos.pop();
604 String expr = getExpression();
605 jos.push(new Operand(
606 "(" + expr + ") ? " + op1.getValueEx(L_TERN)
607 + " : ",
608 op1.getDatatype(), L_TERN));
609 } else {
610 method.closeBlock();
611 //Set the index ptr to the ins after the end of this
612 //block
613 //JInstruction sIns = method.getInstruction(TargetPc);
614 //decomp.setLastIns(sIns.getTargetPc2());
615 //decomp.setLastInsPos(
616 // method.getInstruction(
617 // sIns.getTargetPc2()).position);
618 //System.out.println("End sync - setting end to: "
619 // + sIns.getTargetPc());
620 // System.out.println(method.getName()+":if2
621 // StartPC="+StartPc+" NextPc="+NextPc+" TargetPc="
622 // +TargetPc);
623 // decomp.setLastIns(NextPc);
624 // decomp.setLastInsPos(?);
625 }
626 break;
627 case TYPE_ELSE:
628 if (written) {
629 method.closeBlock();
630 //Set the index ptr to the ins after the end of this
631 //block
632 //JInstruction sIns = method.getInstruction(TargetPc);
633 //decomp.setLastIns(sIns.getTargetPc2());
634 //decomp.setLastInsPos(
635 // method.getInstruction(
636 // sIns.getTargetPc2()).position);
637 //System.out.println("End sync - setting end to: "
638 // + sIns.getTargetPc());
639 // System.out.println(method.getName()+":else
640 // StartPC="+StartPc+" NextPc="+NextPc+" TargetPc="
641 // +TargetPc);
642 //decomp.setLastIns(NextPc);
643 //decomp.setLastInsPos(?);
644 } else {
645 if (!jos.empty()) {
646 //Rollback (remove current else block)
647 method.removeCurrentBlock();
648 }
649 mergeStack = true;
650 }
651 break;
652 case TYPE_TRY:
653 case TYPE_ELSE_IF:
654 case TYPE_WHILE:
655 case TYPE_JSR:
656 case TYPE_SWITCH:
657 case TYPE_CASE:
658 method.closeBlock();
659 //Set the index ptr to the ins after the end of this block
660 //JInstruction sIns = method.getInstruction(TargetPc);
661 //decomp.setLastIns(sIns.getTargetPc2());
662 //decomp.setLastInsPos(method.getInstruction(
663 // sIns.getTargetPc2()).position);
664 //System.out.println("End sync - setting end to: "
665 // + sIns.getTargetPc());
666 ///System.out.println(method.getName()
667 // + ":try/elseif... StartPC="
668 // + StartPc+" NextPc="+NextPc+" TargetPc="
669 // + TargetPc);
670 //decomp.setLastIns(NextPc);
671 //decomp.setLastInsPos(?);
672 break;
673 //Blocks that use "goto i" at targetPc to identify next
674 //instruction
675 case TYPE_CATCH:
676 case TYPE_SYNC:
677 method.closeBlock();
678
679 //Set the index ptr to the ins after the end of this
680 //block, IF no other catch follows
681 /**
682 * JInstruction sIns = method.getInstruction(targetPc);
683 if (targetPc > 0) {
684 // Verified that this works for catch stmts
685 decomp.setLastIns(sIns.index);
686 decomp.setLastInsPos(sIns.position);
687 //decomp.setLastIns(sIns.getTargetPc2());
688 //decomp.setLastInsPos(method.getInstruction(
689 // sIns.getTargetPc2()).position);
690 //
691 }
692 */
693 break;
694 case TYPE_DO_WHILE:
695 method.closeBlock();
696 decomp.setLastIns(nextPc);
697 //decomp.setLastInsPos(?);
698 ((JDoWhileBlock) block).setVar1(opr1);
699 ((JDoWhileBlock) block).setOper(operator);
700 ((JDoWhileBlock) block).setVar2(opr2);
701 //Set the index ptr to the ins after the end of this block
702
703 //JInstruction sIns = method.getInstruction(TargetPc);
704 //decomp.setLastIns(sIns.getTargetPc2());
705 //decomp.setLastInsPos(method.getInstruction(
706 // sIns.getTargetPc2()).position);
707 //System.out.println("End sync - setting end to: "
708 // +sIns.getTargetPc());
709 // System.out.println("do_while");
710 // System.out.println("do_while StartPC="
711 // +StartPc+" NextPc="
712 // +NextPc+" TargetPc="+TargetPc);
713 break;
714 default:
715 }
716 }
717 return mergeStack;
718 }
719
720
721 /**
722 * This merges the current condition represented by the
723 * current JBranchEntry.
724 * @param nextEntry Next Condition that is to be merged with
725 * the current condition.
726 * @param conditionType If OR or AND.
727 * @param complement if the current expression needs to be
728 * complemented.
729 **/
730 public void rewriteCondition(JBranchEntry nextEntry,
731 String conditionType,
732 boolean complement) {
733 opr1 = this.getCondition(complement);
734 operator = conditionType;
735 opr2 = nextEntry.getCondition(true);
736 }
737
738
739 /**
740 * Sets the end pc of this block.
741 * @param aNewPc New Pc that is to be set as the
742 * end of the block
743 **/
744 public void setEndBlockPc(int aNewPc) {
745 switch(type) {
746 case TYPE_IF:
747 case TYPE_ELSE:
748 case TYPE_ELSE_IF:
749 case TYPE_TRY:
750 case TYPE_TRY_ANY:
751 case TYPE_CATCH:
752 case TYPE_CATCH_ANY:
753 case TYPE_JSR:
754 case TYPE_SYNC:
755 case TYPE_CASE:
756 case TYPE_SWITCH:
757 targetPc = aNewPc;
758 break;
759 case TYPE_WHILE:
760 case TYPE_DO_WHILE:
761 nextPc = aNewPc;
762 break;
763 }
764 }
765
766
767 /**
768 * Given the index to the entry in the BranchTable , this
769 * returns the condition .
770 * <p>
771 * For example , if an entry has <br>
772 * <code>4: i 3 != </code> .<br>
773 * Then <code>getCondition(4,true)</code> yields
774 * <code>i != 3 </code> and <br>
775 * <code>getCondition(4,false)</code> yields
776 * <code>i == 3 </code></p> .
777 *
778 * @param complement If flag is set the operator is replaced by its
779 * complement. For eg, complement of >= is replaced by '<''.
780 * @return Returns the condition.
781 **/
782 private String getCondition(boolean complement) {
783 if (!complement) {
784 operator = getComplementOperator(operator);
785 }
786 return getExpression();
787 }
788
789
790
791 /**
792 * Returns the complementary operator of the given operator.
793 * <p>
794 * @param rhs Operator for which complement is to be returned.
795 * @return the complementary operator of <code>Rhs</code>
796 **/
797 private String getComplementOperator(String rhs) {
798 if (rhs.compareTo(OPR_GT) == 0) {
799 return OPR_LE;
800 } else if (rhs.compareTo(OPR_GE) == 0) {
801 return OPR_LT;
802 } else if (rhs.compareTo(OPR_LT) == 0) {
803 return OPR_GE;
804 } else if (rhs.compareTo(OPR_LE) == 0) {
805 return OPR_GT;
806 } else if (rhs.compareTo(OPR_EQ) == 0) {
807 return OPR_NE;
808 } else if (rhs.compareTo(OPR_NE) == 0) {
809 return OPR_EQ;
810 } else {
811 return rhs;
812 }
813 }
814
815 /**
816 * Trims the expression for a condition here.
817 * For eg, an expression of the form -
818 * if ( a == true ) is converted to 'a' ( just 'a' ).
819 * These small modifications improve the readability of the code.
820 * @return Returns the new code.
821 **/
822 public String getExpression() {
823 operator = operator.trim();
824 opr2 = opr2.trim();
825
826 if (opr2.equals(FALSE)) {
827 if (operator.equals(OPR_EQ)) {
828 return OPR_NOT + opr1;
829 }
830 return opr1;
831 } else if (opr2.equals(TRUE)) {
832 if (operator.equals(OPR_EQ)) {
833 return opr1;
834 }
835 return OPR_NOT + opr1;
836 } else {
837 return opr1 + " " + operator + " " + opr2;
838 }
839 }
840
841 /**
842 * @return Returns the Stringified representation of the
843 * class.
844 **/
845 public String toString() {
846 StringBuffer sb = new StringBuffer(" ");
847 sb.append(written + " ");
848 sb.append(startPc + " " + nextPc + " " + targetPc + " ");
849 switch(type) {
850 case TYPE_IF:
851 sb.append("TYPE_IF");
852 break;
853 case TYPE_ELSE_IF:
854 sb.append("TYPE_ELSE_IF");
855 break;
856 case TYPE_ELSE:
857 sb.append("TYPE_ELSE");
858 break;
859 case TYPE_DO_WHILE:
860 sb.append("TYPE_DO_WHILE");
861 break;
862 case TYPE_TRY:
863 sb.append("TYPE_TRY");
864 break;
865 case TYPE_TRY_ANY:
866 sb.append("TYPE_TRY_ANY");
867 break;
868 case TYPE_CATCH:
869 sb.append("TYPE_CATCH");
870 break;
871 case TYPE_CATCH_ANY:
872 sb.append("TYPE_CATCH_ANY");
873 break;
874 case TYPE_WHILE:
875 sb.append("TYPE_WHILE");
876 break;
877 case TYPE_JSR:
878 sb.append("TYPE_JSR");
879 break;
880 case TYPE_SYNC:
881 sb.append("TYPE_SYNCHRONIZED");
882 break;
883 case TYPE_CASE:
884 sb.append("TYPE_CASE");
885 break;
886 case TYPE_SWITCH:
887 sb.append("TYPE_SWITCH");
888 break;
889 default:
890 sb.append(type);
891 }
892 sb.append(" " + opr1 + " " + operator + " " + opr2);
893 return sb.toString();
894 }
895 }