Adding notes in the latest changes for the serializer bug fix.
[jpf-core.git] / src / main / gov / nasa / jpf / vm / JPFOutputStream.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.vm;
19
20 import java.io.IOException;
21 import java.io.OutputStream;
22 import java.io.PrintStream;
23
24 import gov.nasa.jpf.util.FinalBitSet;
25 import gov.nasa.jpf.util.PrintUtils;
26
27 /**
28  * stream to write program state info in a readable and diff-able format.
29  * This is mostly intended for debugging, but could also at some point be
30  * used to restore such states.
31  * 
32  * Currently supports heap objects, classes (static fields), threads and stack frames
33  */
34 public class JPFOutputStream extends OutputStream {
35   
36   PrintStream ps;
37   
38   boolean useSid = false;
39   int maxElements = -1;
40   
41   public JPFOutputStream (OutputStream os){
42     ps = new PrintStream(os);
43   }
44   
45   public JPFOutputStream (PrintStream ps){
46     this.ps = ps;
47   }
48   
49   public JPFOutputStream (){
50     this(System.out);
51   }
52   
53   @Override
54   public void close(){
55     ps.flush();
56     
57     if (ps != System.err && ps != System.out){
58       ps.close();
59     }
60   }
61   
62   public void printCommentLine(String msg){
63     ps.print("// ");
64     ps.println(msg);
65   }
66   
67   public void print (ElementInfo ei, FieldInfo fi, boolean isFiltered){
68     ps.print(fi.getName());
69     ps.print(':');
70
71     if (isFiltered){
72       ps.print("X");
73       
74     } else {
75       switch (fi.getTypeCode()) {
76       case Types.T_BOOLEAN:
77         ps.print(ei.getBooleanField(fi));
78         break;
79       case Types.T_BYTE:
80         ps.print(ei.getByteField(fi));
81         break;
82       case Types.T_CHAR:
83         PrintUtils.printCharLiteral(ps, ei.getCharField(fi));
84         break;
85       case Types.T_SHORT:
86         ps.print(ei.getShortField(fi));
87         break;
88       case Types.T_INT:
89         ps.print(ei.getIntField(fi));
90         break;
91       case Types.T_LONG:
92         ps.print(ei.getLongField(fi));
93         break;
94       case Types.T_FLOAT:
95         ps.print(ei.getFloatField(fi));
96         break;
97       case Types.T_DOUBLE:
98         ps.print(ei.getDoubleField(fi));
99         break;
100
101       case Types.T_REFERENCE:
102       case Types.T_ARRAY:
103         PrintUtils.printReference(ps, ei.getReferenceField(fi));
104         break;
105       }
106     }
107   }
108   
109   protected void printFields (ElementInfo ei, FieldInfo[] fields, FinalBitSet filterMask){
110     if (fields != null){
111       for (int i = 0; i < fields.length; i++) {
112         if (i > 0) {
113           ps.print(',');
114         }
115         print(ei, fields[i], (filterMask != null && filterMask.get(i)));
116       }
117     }
118   }
119   
120   public void print (ElementInfo ei, FinalBitSet filterMask){
121     boolean isObject = ei.isObject();
122     ClassInfo ci = ei.getClassInfo();
123
124     // TODO: Fix for Groovy's model-checking
125     // TODO: Change of sid assignment strategy since the previous one caused a bug with SmartThings object filtering
126     int ref = (useSid) ? ((int)ei.getSid()) : ei.getObjectRef();
127     ps.printf("@%x ", ref);
128     
129     if (isObject){
130       ps.print("object ");
131       if (ei.isArray()){
132         ps.print( Types.getTypeName(ci.getName()));
133       } else {
134         ps.print(ci.getName());
135       }
136     } else {
137       ps.print("class ");
138       ps.print(ci.getName());
139     }
140     
141     ps.print(':');
142     
143     if (isObject){
144       if (ei.isArray()){
145         ps.print('[');
146         ei.getArrayFields().printElements(ps, maxElements);
147         ps.print(']');
148             
149       } else {
150         ps.print('{');
151         printFields(ei, ci.getInstanceFields(), filterMask);
152         ps.print('}');
153       }
154       
155     } else {
156       ps.print('{');
157       printFields( ei, ci.getDeclaredStaticFields(), filterMask);        
158       ps.print('}');
159     }
160   }
161   
162   public void print (ThreadInfo ti){
163     PrintUtils.printReference(ps, ti.getThreadObjectRef());
164     ps.print(' ');
165     ps.print(ti.getStateDescription());
166   }
167   
168   public void print (StackFrame frame){
169     MethodInfo mi = frame.getMethodInfo();
170   
171     ps.print('@');
172     ps.print(frame.getDepth());
173     
174     ps.print(" frame ");
175     ps.print( mi.getFullName());
176     ps.print( ":{" );
177     
178     if (!mi.isStatic()){
179       ps.print("this:");
180       PrintUtils.printReference(ps, frame.getThis());
181       ps.print(',');
182     }
183     
184     ps.print("pc:");
185     ps.print(frame.getPC().getInstructionIndex());
186     
187     ps.print(",slots:[");
188     frame.printSlots(ps);
189     ps.print(']');
190     
191     ps.print('}');
192   }
193   
194   public void println(){
195     ps.println();
196   }
197   
198   public void print (NativeStateHolder nsh){
199     ps.print(nsh);
200     ps.print(":");
201     ps.print(nsh.getHash());
202   }
203   
204   @Override
205   public void write(int b) throws IOException {
206     ps.write(b);
207   }
208 }