00001 package edu.ksu.cis.bandera.abstraction.options;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.io.*;
00036 import java.util.*;
00037 import java.lang.reflect.Method;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040 import edu.ksu.cis.bandera.abstraction.util.*;
00041 import edu.ksu.cis.bandera.abstraction.options.node.*;
00042 import edu.ksu.cis.bandera.abstraction.options.lexer.*;
00043 import edu.ksu.cis.bandera.abstraction.options.parser.*;
00044 import edu.ksu.cis.bandera.abstraction.options.analysis.*;
00045 public class OptionsSaverLoader {
00046 private static final Jimple jimple = Jimple.v();
00047 private Hashtable localMethodNamesTable;
00048 private SootClassManager scm;
00049 private SootClass sc;
00050 private SootMethod sm;
00051 private ca.mcgill.sable.util.List params;
00052 private JimpleBody body;
00053 private Hashtable result;
00054 private Vector warnings;
00055 private class Walker extends DepthFirstAdapter {
00056 public void caseAClassOption(AClassOption node) {
00057 sc = scm.getClass(Util.deleteChars(node.getName().toString(), " "));
00058 if (result.get(sc) != null) {
00059 String msg = "*** WARNING: Redefinition of options for class '" + sc + "'. Discarding the previous one. ****";
00060 warnings.add(msg);
00061
00062 }
00063 result.put(sc, new HashSet());
00064 {
00065 Object temp[] = node.getFieldOption().toArray();
00066 for (int i = 0; i < temp.length; i++) {
00067 ((PFieldOption) temp[i]).apply(this);
00068 }
00069 }
00070 {
00071 Object temp[] = node.getMethodOption().toArray();
00072 for (int i = 0; i < temp.length; i++) {
00073 ((PMethodOption) temp[i]).apply(this);
00074 }
00075 }
00076 }
00077 public void caseAFieldOption(AFieldOption node) {
00078 String fieldName = node.getId().toString().trim();
00079 if (sc.declaresField(fieldName)) {
00080 String typeName = Util.deleteChars(node.getName().toString(), " ");
00081 try {
00082 SootField sf = sc.getField(fieldName);
00083 result.put(sf, AbstractionClassLoader.getClass(typeName).getMethod("v", new Class[0]).invoke(null, new Object[0]));
00084 ((HashSet) result.get(sc)).add(sf);
00085 } catch (Exception e) {
00086 String msg = "*** WARNING: Couldn't find abstraction '" + typeName + "'. The '" + sc.getName() + "." + fieldName + "' field's option is ignored. ***";
00087 warnings.add(msg);
00088
00089 }
00090 } else {
00091 String msg = "*** WARNING: Couldn't find field '" + sc.getName() + "." + fieldName + "'. The field's option is ignored. ***";
00092 warnings.add(msg);
00093
00094 }
00095 }
00096 public void caseALocalOption(ALocalOption node) {
00097 String localName = node.getId().toString().trim();
00098 if (body.declaresLocal(localName)) {
00099 LocalMethod lm = new LocalMethod(sm, body.getLocal(localName));
00100 String typeName = Util.deleteChars(node.getName().toString(), " ");
00101 try {
00102 result.put(lm, AbstractionClassLoader.getClass(typeName).getMethod("v", new Class[0]).invoke(null, new Object[0]));
00103 ((HashSet) result.get(sm)).add(lm.getLocal());
00104 } catch (Exception e) {
00105 String msg = "*** WARNING: Couldn't find abstraction '" + typeName + "'. The '" + lm + "' local's option is ignored. ***";
00106 warnings.add(msg);
00107
00108 }
00109 } else {
00110 String msg = "*** WARNING: Couldn't find local '" + localName + "' in method '" + sm + "'. The local's option is ignored. ***";
00111 warnings.add(msg);
00112
00113 }
00114 }
00115 public void caseAMethodOption(AMethodOption node) {
00116 params = new ca.mcgill.sable.util.LinkedList();
00117 if (node.getParams() != null) {
00118 node.getParams().apply(this);
00119 }
00120 String mName = node.getId().toString().trim();
00121 String cName = sc.getName();
00122 int idx = cName.lastIndexOf(".");
00123 if (idx >= 0) {
00124 cName = cName.substring(idx + 1);
00125 }
00126 if (mName.equals(cName)) mName = "<init>";
00127 try {
00128 sm = sc.getMethod(mName, params);
00129 ((HashSet) result.get(sc)).add(sm);
00130 if (!sm.isBodyStored(jimple)) {
00131 new BuildAndStoreBody(jimple, new StoredBody(ClassFile.v()), 0).resolveFor(sm);
00132 }
00133 body = (JimpleBody) sm.getBody(jimple);
00134 result.put(sm, new HashSet());
00135 {
00136 Object temp[] = node.getLocalOption().toArray();
00137 for (int i = 0; i < temp.length; i++) {
00138 ((PLocalOption) temp[i]).apply(this);
00139 }
00140 }
00141 } catch (Exception e) {
00142 String params = OptionsSaverLoader.this.params.toString();
00143 params = params.substring(1, params.length() - 1);
00144 String msg = "*** WARNING: Couldn't find method '" + sc.getName() + "." + mName + "(" + params + ")'. The method's options are ignored. ***";
00145 warnings.add(msg);
00146
00147 }
00148 }
00149 public void caseAParamParams(AParamParams node) {
00150 Type t = Util.getType(Util.deleteChars(node.getName().toString(), " "));
00151 int dimensions = node.getDim().size();
00152 if (dimensions > 0) {
00153 t = ArrayType.v((BaseType) t, dimensions);
00154 }
00155 params.add(t);
00156 }
00157 public void caseAParamsParams(AParamsParams node) {
00158 node.getParams().apply(this);
00159 Type t = Util.getType(Util.deleteChars(node.getName().toString(), " "));
00160 int dimensions = node.getDim().size();
00161 if (dimensions > 0) {
00162 t = ArrayType.v((BaseType) t, dimensions);
00163 }
00164 params.add(t);
00165 }
00166 }
00167 private Walker walker;
00168
00169
00170
00171 private OptionsSaverLoader() {
00172 walker = new Walker();
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 public static Hashtable load(SootClassManager scm, Reader reader) throws Exception {
00187 OptionsSaverLoader osl = new OptionsSaverLoader();
00188 osl.scm = scm;
00189
00190 osl.result = new Hashtable();
00191 osl.warnings = new Vector();
00192
00193 new Parser(new Lexer(new PushbackReader(reader))).parse().apply(osl.walker);
00194
00195 osl.result.put("WARNINGS", osl.warnings);
00196
00197 return osl.result;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 public static void save(PrintWriter writer, Hashtable table) {
00210 for (Enumeration e = table.keys(); e.hasMoreElements();) {
00211 Object key = e.nextElement();
00212 if (key instanceof SootClass) {
00213 SootClass sc = (SootClass) key;
00214 writer.println("class " + sc.getName() + " {");
00215 for (Iterator i = ((HashSet) table.get(sc)).iterator(); i.hasNext();) {
00216 Object o = i.next();
00217 if (o instanceof SootField) {
00218 SootField sf = (SootField) o;
00219 writer.println(" " + sf.getName() + " " + table.get(sf).getClass().getName() + ";");
00220 }
00221 }
00222 for (Iterator i = ((HashSet) table.get(sc)).iterator(); i.hasNext();) {
00223 Object o = i.next();
00224 if (o instanceof SootMethod) {
00225 SootMethod sm = (SootMethod) o;
00226 String mName = sm.getName();
00227 if ("<clinit>".equals(mName)) continue;
00228 if ("<init>".equals(mName)) {
00229 mName = sm.getDeclaringClass().getName();
00230 int idx = mName.lastIndexOf(".");
00231 if (idx >= 0) {
00232 mName = mName.substring(idx + 1);
00233 }
00234 }
00235 String params = sm.getParameterTypes().toString();
00236 writer.println(" " + mName + "(" + params.substring(1, params.length() - 1) + ") { ");
00237 for (Iterator j = ((HashSet) table.get(sm)).iterator(); j.hasNext();) {
00238 Local lcl = (Local) j.next();
00239 writer.println(" " + lcl.getName() + " " + table.get(new LocalMethod(sm, lcl)).getClass().getName() + ";");
00240 }
00241 writer.println(" }");
00242 }
00243 }
00244 writer.println("}");
00245 writer.println();
00246 }
00247 }
00248 }
00249 }