Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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 }