KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > Printer


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2003 Ondrej Lhotak
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 /*
21  * Modified by the Sable Research Group and others 1997-1999.
22  * See the 'credits' file distributed with Soot for the complete list of
23  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
24  */

25
26 package soot;
27 import soot.options.*;
28 import java.io.*;
29 import soot.tagkit.*;
30 import java.util.*;
31 import soot.util.*;
32 import soot.toolkits.graph.*;
33
34 /**
35 * Prints out a class and all its methods.
36 */

37 public class Printer {
38     public Printer(Singletons.Global g) {
39     }
40     public static Printer v() {
41         return G.v().soot_Printer();
42     }
43
44     final private static char fileSeparator =
45         System.getProperty("file.separator").charAt(0);
46
47     public static final int USE_ABBREVIATIONS = 0x0001, ADD_JIMPLE_LN = 0x0010;
48
49     public boolean useAbbreviations() {
50         return (options & USE_ABBREVIATIONS) != 0;
51     }
52
53     public boolean addJimpleLn() {
54         return (options & ADD_JIMPLE_LN) != 0;
55     }
56
57     int options = 0;
58     public void setOption(int opt) {
59         options |= opt;
60     }
61     public void clearOption(int opt) {
62         options &= ~opt;
63     }
64
65     int jimpleLnNum = 0; // actual line number
66

67     public int getJimpleLnNum() {
68         return jimpleLnNum;
69     }
70     public void setJimpleLnNum(int newVal) {
71         jimpleLnNum = newVal;
72     }
73     public void incJimpleLnNum() {
74         jimpleLnNum++;
75     //G.v().out.println("jimple Ln Num: "+jimpleLnNum);
76
}
77
78     public void printTo(SootClass cl, PrintWriter out) {
79         // add jimple line number tags
80
setJimpleLnNum(1);
81
82         // Print class name + modifiers
83
{
84             StringTokenizer st =
85                 new StringTokenizer(Modifier.toString(cl.getModifiers()));
86             while (st.hasMoreTokens()) {
87                 String JavaDoc tok = (String JavaDoc) st.nextToken();
88                 if( cl.isInterface() && tok.equals("abstract") ) continue;
89                 out.print(tok + " ");
90             }
91
92             String JavaDoc classPrefix = "";
93
94             if (!cl.isInterface()) {
95                 classPrefix = classPrefix + " class";
96                 classPrefix = classPrefix.trim();
97             }
98
99             out.print(
100                 classPrefix + " " + Scene.v().quotedNameOf(cl.getName()) + "");
101         }
102
103         // Print extension
104
{
105             if (cl.hasSuperclass())
106                 out.print(
107                     " extends "
108                         + Scene.v().quotedNameOf(cl.getSuperclass().getName())
109                         + "");
110         }
111
112         // Print interfaces
113
{
114             Iterator interfaceIt = cl.getInterfaces().iterator();
115
116             if (interfaceIt.hasNext()) {
117                 out.print(" implements ");
118
119                 out.print(
120                     ""
121                         + Scene.v().quotedNameOf(
122                             ((SootClass) interfaceIt.next()).getName())
123                         + "");
124
125                 while (interfaceIt.hasNext()) {
126                     out.print(",");
127                     out.print(
128                         " "
129                             + Scene.v().quotedNameOf(
130                                 ((SootClass) interfaceIt.next()).getName())
131                             + "");
132                 }
133             }
134         }
135
136         out.println();
137         incJimpleLnNum();
138 /* if (!addJimpleLn()) {
139             Iterator clTagsIt = cl.getTags().iterator();
140             while (clTagsIt.hasNext()) {
141                 final Tag t = (Tag)clTagsIt.next();
142                 out.println(t);
143             }
144         }*/

145         out.println("{");
146         incJimpleLnNum();
147         if (Options.v().print_tags_in_output()){
148             Iterator cTagIterator = cl.getTags().iterator();
149             while (cTagIterator.hasNext()) {
150                 Tag t = (Tag) cTagIterator.next();
151                 out.print("/*");
152                 out.print(t.toString());
153                 out.println("*/");
154             }
155         }
156
157         // Print fields
158
{
159             Iterator fieldIt = cl.getFields().iterator();
160
161             if (fieldIt.hasNext()) {
162                 while (fieldIt.hasNext()) {
163                     SootField f = (SootField) fieldIt.next();
164
165                     if (f.isPhantom())
166                         continue;
167
168                     if (Options.v().print_tags_in_output()){
169                         Iterator fTagIterator = f.getTags().iterator();
170                         while (fTagIterator.hasNext()) {
171                             Tag t = (Tag) fTagIterator.next();
172                             out.print("/*");
173                             out.print(t.toString());
174                             out.println("*/");
175                         }
176                     }
177                     out.println(" " + f.getDeclaration() + ";");
178                     if (addJimpleLn()) {
179                         setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), f));
180                     }
181
182                     //incJimpleLnNum();
183
}
184             }
185         }
186
187         // Print methods
188
{
189             Iterator methodIt = cl.methodIterator();
190
191             if (methodIt.hasNext()) {
192                 if (cl.getMethodCount() != 0) {
193                     out.println();
194                     incJimpleLnNum();
195                 }
196
197                 while (methodIt.hasNext()) {
198                     SootMethod method = (SootMethod) methodIt.next();
199
200                     if (method.isPhantom())
201                         continue;
202
203                     if (!Modifier.isAbstract(method.getModifiers())
204                         && !Modifier.isNative(method.getModifiers())) {
205                         if (!method.hasActiveBody())
206                             throw new RuntimeException JavaDoc(
207                                 "method "
208                                     + method.getName()
209                                     + " has no active body!");
210                         else
211                             if (Options.v().print_tags_in_output()){
212                                 Iterator mTagIterator = method.getTags().iterator();
213                                 while (mTagIterator.hasNext()) {
214                                     Tag t = (Tag) mTagIterator.next();
215                                     out.print("/*");
216                                     out.print(t.toString());
217                                     out.println("*/");
218                                 }
219                             }
220                             printTo(method.getActiveBody(), out);
221
222                         if (methodIt.hasNext()) {
223                             out.println();
224                             incJimpleLnNum();
225                         }
226                     } else {
227                            
228                         if (Options.v().print_tags_in_output()){
229                             Iterator mTagIterator = method.getTags().iterator();
230                             while (mTagIterator.hasNext()) {
231                                 Tag t = (Tag) mTagIterator.next();
232                                 out.print("/*");
233                                 out.print(t.toString());
234                                 out.println("*/");
235                             }
236                         }
237                         
238                         out.print(" ");
239                         out.print(method.getDeclaration());
240                         out.println(";");
241                         incJimpleLnNum();
242                         if (methodIt.hasNext()) {
243                             out.println();
244                             incJimpleLnNum();
245                         }
246                     }
247                 }
248             }
249         }
250         out.println("}");
251         incJimpleLnNum();
252     }
253
254     /**
255         Writes the class out to a file.
256      */

257     // This method is deprecated. Use soot.util.JasminOutputStream instead.
258
public void writeXXXDeprecated(SootClass cl, String JavaDoc outputDir) {
259         String JavaDoc outputDirWithSep = "";
260
261         if (!outputDir.equals(""))
262             outputDirWithSep = outputDir + fileSeparator;
263
264         try {
265             File tempFile =
266                 new File(outputDirWithSep + cl.getName() + ".jasmin");
267
268             FileOutputStream streamOut = new FileOutputStream(tempFile);
269
270             PrintWriter writerOut =
271                 new PrintWriter(
272                     new EscapedWriter(new OutputStreamWriter(streamOut)));
273
274             if (cl.containsBafBody())
275                 new soot.baf.JasminClass(cl).print(writerOut);
276             else
277                 new soot.jimple.JasminClass(cl).print(writerOut);
278
279             writerOut.close();
280
281             if (Options.v().time())
282                 Timers.v().assembleJasminTimer.start();
283
284             // Invoke jasmin
285
{
286                 String JavaDoc[] args;
287
288                 if (outputDir.equals("")) {
289                     args = new String JavaDoc[1];
290
291                     args[0] = cl.getName() + ".jasmin";
292                 } else {
293                     args = new String JavaDoc[3];
294
295                     args[0] = "-d";
296                     args[1] = outputDir;
297                     args[2] = outputDirWithSep + cl.getName() + ".jasmin";
298                 }
299
300                 jasmin.Main.main(args);
301             }
302
303             tempFile.delete();
304
305             if (Options.v().time())
306                 Timers.v().assembleJasminTimer.end();
307
308         } catch (IOException e) {
309             throw new RuntimeException JavaDoc(
310                 "Could not produce new classfile! (" + e + ")");
311         }
312     }
313
314     /**
315      * Prints out the method corresponding to b Body, (declaration and body),
316      * in the textual format corresponding to the IR used to encode b body.
317      *
318      * @param out a PrintWriter instance to print to.
319      */

320     public void printTo(Body b, PrintWriter out) {
321         b.validate();
322
323         boolean isPrecise = !useAbbreviations();
324
325         String JavaDoc decl = b.getMethod().getDeclaration();
326
327         out.println(" " + decl);
328         //incJimpleLnNum();
329

330         // only print tags if not printing attributes in a file
331
if (!addJimpleLn()) {
332             /*for( Iterator tIt = b.getMethod().getTags().iterator(); tIt.hasNext(); ) { final Tag t = (Tag) tIt.next();
333                 out.println(t);
334                 incJimpleLnNum();
335
336             }*/

337         }
338        
339         if (addJimpleLn()) {
340             setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), b.getMethod()));
341             //G.v().out.println("added jimple ln tag for method: "+b.getMethod().toString()+" "+b.getMethod().getDeclaringClass().getName());
342
}
343
344         out.println(" {");
345         incJimpleLnNum();
346         
347         UnitGraph unitGraph = new soot.toolkits.graph.BriefUnitGraph(b);
348
349         LabeledUnitPrinter up;
350         if( isPrecise ) up = new NormalUnitPrinter(b);
351         else up = new BriefUnitPrinter(b);
352
353         if (addJimpleLn()) {
354             up.setPositionTagger( new AttributesUnitPrinter(getJimpleLnNum()) );
355         }
356     
357         printLocalsInBody(b, up);
358
359         printStatementsInBody(b, out, up, unitGraph);
360
361         out.println(" }");
362         incJimpleLnNum();
363
364     }
365
366     /** Prints the given <code>JimpleBody</code> to the specified <code>PrintWriter</code>. */
367     private void printStatementsInBody(Body body, java.io.PrintWriter JavaDoc out, LabeledUnitPrinter up, UnitGraph unitGraph ) {
368         Chain units = body.getUnits();
369         Iterator unitIt = units.iterator();
370         Unit currentStmt = null, previousStmt;
371
372         while (unitIt.hasNext()) {
373
374             previousStmt = currentStmt;
375             currentStmt = (Unit) unitIt.next();
376
377             // Print appropriate header.
378
{
379                 // Put an empty line if the previous node was a branch node, the current node is a join node
380
// or the previous statement does not have body statement as a successor, or if
381
// body statement has a label on it
382

383                 if (currentStmt != units.getFirst()) {
384                     if (unitGraph.getSuccsOf(previousStmt).size() != 1
385                         || unitGraph.getPredsOf(currentStmt).size() != 1
386                         || up.labels().containsKey(currentStmt)) {
387                         up.newline();
388                     } else {
389                         // Or if the previous node does not have body statement as a successor.
390

391                         List succs = unitGraph.getSuccsOf(previousStmt);
392
393                         if (succs.get(0) != currentStmt) {
394                             up.newline();
395                         }
396                     }
397                 }
398
399                 if (up.labels().containsKey(currentStmt)) {
400                     up.unitRef( currentStmt, true );
401                     up.literal(":");
402                     up.newline();
403                 }
404
405                 if (up.references().containsKey(currentStmt)) {
406                     up.unitRef( currentStmt, false );
407                 }
408             }
409
410             up.startUnit(currentStmt);
411             currentStmt.toString(up);
412             up.endUnit(currentStmt);
413
414             up.literal(";");
415             up.newline();
416
417             // only print them if not generating attributes files
418
// because they mess up line number
419
//if (!addJimpleLn()) {
420
if (Options.v().print_tags_in_output()){
421                 Iterator tagIterator = currentStmt.getTags().iterator();
422                 while (tagIterator.hasNext()) {
423                     Tag t = (Tag) tagIterator.next();
424                     up.noIndent();
425                     up.literal("/*");
426                     up.literal(t.toString());
427                     up.literal("*/");
428                     up.newline();
429                 }
430                 /*Iterator udIt = currentStmt.getUseAndDefBoxes().iterator();
431                 while (udIt.hasNext()) {
432                     ValueBox temp = (ValueBox)udIt.next();
433                     Iterator vbtags = temp.getTags().iterator();
434                     while (vbtags.hasNext()) {
435                         Tag t = (Tag) vbtags.next();
436                         up.noIndent();
437                         up.literal("VB Tag: "+t.toString());
438                         up.newline();
439                     }
440                 }*/

441             }
442         }
443
444         out.print(up.toString());
445         if (addJimpleLn()){
446             setJimpleLnNum(up.getPositionTagger().getEndLn());
447         }
448
449
450         // Print out exceptions
451
{
452             Iterator trapIt = body.getTraps().iterator();
453
454             if (trapIt.hasNext()) {
455                 out.println();
456                 incJimpleLnNum();
457             }
458
459             while (trapIt.hasNext()) {
460                 Trap trap = (Trap) trapIt.next();
461
462                 out.println(
463                     " catch "
464                         + Scene.v().quotedNameOf(trap.getException().getName())
465                         + " from "
466                         + up.labels().get(trap.getBeginUnit())
467                         + " to "
468                         + up.labels().get(trap.getEndUnit())
469                         + " with "
470                         + up.labels().get(trap.getHandlerUnit())
471                         + ";");
472
473                 incJimpleLnNum();
474
475             }
476         }
477
478     }
479
480     private int addJimpleLnTags(int lnNum, Unit stmt, int endLn) {
481         
482         if (endLn-lnNum <= 1) {
483             stmt.addTag(new JimpleLineNumberTag(lnNum));
484             //G.v().out.println(stmt.getClass().toString());
485
lnNum++;
486             return lnNum;
487         }
488         else {
489             stmt.addTag(new JimpleLineNumberTag(lnNum, endLn));
490             //G.v().out.println("multi-line: "+stmt.getClass().toString());
491
endLn++;
492             return endLn;
493         }
494     }
495
496     private int addJimpleLnTags(int lnNum, SootMethod meth) {
497         meth.addTag(new JimpleLineNumberTag(lnNum));
498     lnNum++;
499     return lnNum;
500     }
501     
502     private int addJimpleLnTags(int lnNum, SootField f) {
503         f.addTag(new JimpleLineNumberTag(lnNum));
504     lnNum++;
505     return lnNum;
506     }
507
508     /** Prints the given <code>JimpleBody</code> to the specified <code>PrintWriter</code>. */
509     private void printLocalsInBody(
510         Body body,
511         UnitPrinter up) {
512         // Print out local variables
513
{
514             Map typeToLocals =
515                 new DeterministicHashMap(body.getLocalCount() * 2 + 1, 0.7f);
516
517             // Collect locals
518
{
519                 Iterator localIt = body.getLocals().iterator();
520
521                 while (localIt.hasNext()) {
522                     Local local = (Local) localIt.next();
523
524                     List localList;
525
526                     Type t = local.getType();
527
528                     if (typeToLocals.containsKey(t))
529                         localList = (List) typeToLocals.get(t);
530                     else {
531                         localList = new ArrayList();
532                         typeToLocals.put(t, localList);
533                     }
534
535                     localList.add(local);
536                 }
537             }
538
539             // Print locals
540
{
541                 Iterator typeIt = typeToLocals.keySet().iterator();
542
543                 while (typeIt.hasNext()) {
544                     Type type = (Type) typeIt.next();
545
546                     List localList = (List) typeToLocals.get(type);
547                     Object JavaDoc[] locals = localList.toArray();
548                     up.type( type );
549                     up.literal( " " );
550
551                     for (int k = 0; k < locals.length; k++) {
552                         if (k != 0)
553                             up.literal( ", " );
554
555                         up.local( (Local) locals[k] );
556                     }
557
558                     up.literal(";");
559                     up.newline();
560                 }
561             }
562
563             if (!typeToLocals.isEmpty()) {
564                 up.newline();
565             }
566         }
567     }
568 }
569
Popular Tags