001 package nl.cwi.sen1.tide.adapters; 002 003 import java.lang.reflect.InvocationTargetException; 004 import java.lang.reflect.Method; 005 import java.util.ArrayList; 006 import java.util.List; 007 008 import aterm.ATerm; 009 import aterm.ATermAppl; 010 import aterm.ATermFactory; 011 import aterm.ATermInt; 012 import aterm.ATermList; 013 import aterm.ParseError; 014 015 abstract public class DebugAdapterProcess { 016 private static final int MAXIMUM_METHOD_ARITY = 8; 017 public final static int STATE_STOPPED = 0; 018 public final static int STATE_RUNNING = 1; 019 020 private Class<?>[][] protos = new Class[MAXIMUM_METHOD_ARITY][]; 021 final static int MAX_RULES = 256; 022 public DebugAdapter adapter; 023 024 static private int processId = 0; 025 private String processName; 026 027 private boolean debug = true; 028 029 public DebugAdapterRule[] rules = new DebugAdapterRule[MAX_RULES]; 030 public List<DebugAdapterRule>[] rulesPerPort = (List<DebugAdapterRule>[]) new List[DebugAdapterRule.NR_PORT_TYPES]; 031 public DebugAdapterRule current_rule = null; 032 033 int exec_state = STATE_STOPPED; 034 int start_level = 0; 035 036 private ATermFactory factory; 037 038 ATerm termTrue; 039 ATerm termFalse; 040 ATerm termRunning; 041 ATerm termStopped; 042 ATerm termUnknown; 043 044 public String getProcessName() { 045 return processName; 046 } 047 public DebugAdapterProcess(DebugAdapter adapter, String name) { 048 this.adapter = adapter; 049 this.processName = name; 050 this.factory = adapter.getFactory(); 051 052 for (int i = 0; i < DebugAdapterRule.NR_PORT_TYPES; i++) { 053 rulesPerPort[i] = new ArrayList<DebugAdapterRule>(); 054 } 055 056 initializeATermClassObjects(); 057 058 try { 059 termTrue = factory.parse("true"); 060 termFalse = factory.parse("false"); 061 termRunning = factory.parse("running"); 062 termStopped = factory.parse("stopped"); 063 termUnknown = factory.parse("unknown"); 064 } catch (ParseError e) { 065 throw new RuntimeException( 066 "internal error, malformed term: " + e.getMessage()); 067 } 068 } 069 070 private void initializeATermClassObjects() { 071 try { 072 Class<?> aterm = Class.forName("aterm.ATerm"); 073 for (int i = 0; i < MAXIMUM_METHOD_ARITY; i++) { 074 protos[i] = new Class[i]; 075 for (int j = 0; j < i; j++) 076 protos[i][j] = aterm; 077 } 078 } catch (ClassNotFoundException e) { 079 throw new RuntimeException("could not find class: aterm.ATerm"); 080 } 081 } 082 public int getPid() { 083 return processId; 084 } 085 086 public int getExecState() { 087 return exec_state; 088 } 089 090 public void changeExecState(int newstate) { 091 if (exec_state != newstate) { 092 exec_state = newstate; 093 switch (exec_state) { 094 case STATE_STOPPED : 095 fireRules(DebugAdapterRule.PORT_STOPPED); 096 break; 097 case STATE_RUNNING : 098 fireRules(DebugAdapterRule.PORT_STARTED); 099 break; 100 } 101 } 102 } 103 104 public boolean isRunning() { 105 return exec_state == STATE_RUNNING; 106 } 107 108 public void fireLocationRules(String filename, int sl, int sc, int el,int ec) {} 109 110 public void fireRules(int porttype) { 111 Object[] elems = rulesPerPort[porttype].toArray(); 112 for (int i = 0; i < elems.length; i++) { 113 DebugAdapterRule rule = (DebugAdapterRule) elems[i]; 114 fireRule(rule); 115 } 116 } 117 118 private void debugMsg(String msg) { 119 if (debug) { 120 System.err.println(msg); 121 } 122 } 123 124 public void fireRule(DebugAdapterRule rule) { 125 DebugAdapterRule old_rule = current_rule; 126 current_rule = rule; 127 128 ATerm cond = rule.getCondition(); 129 ATerm result = evaluate(cond); 130 if (result.isEqual(termTrue)) { 131 result = evaluate(rule.getAction()); 132 adapter.event(getPid(), current_rule, result); 133 } 134 135 current_rule = old_rule; 136 } 137 138 public DebugAdapterRule createRule(int pid, ATerm port, ATerm cond, ATerm act, ATerm tag, boolean enabled) { 139 int rid; 140 141 /* Find a free rule */ 142 for (rid = 0; rid < MAX_RULES; rid++) { 143 if (rules[rid] == null) { 144 break; 145 } 146 } 147 148 if (rid >= MAX_RULES) { 149 throw new RuntimeException("too many rules: " + rid); 150 } 151 152 DebugAdapterRule rule = 153 new DebugAdapterRule(rid, port, cond, act, tag, enabled); 154 155 rules[rule.getId()] = rule; 156 157 if (enabled) { 158 enableRule(rid); 159 } 160 161 handleRuleCreation(rule); 162 163 return rule; 164 } 165 166 public void enableRule(int rid) { 167 DebugAdapterRule rule = rules[rid]; 168 int porttype = rule.getPortType(); 169 170 rule.setEnabled(true); 171 synchronized(rulesPerPort[porttype]){ 172 rulesPerPort[porttype].add(rule); 173 } 174 handleRuleEnabling(rule); 175 } 176 177 public void disableRule(int rid) { 178 DebugAdapterRule rule = rules[rid]; 179 int porttype = rule.getPortType(); 180 181 rule.setEnabled(false); 182 synchronized (rulesPerPort[porttype]) { 183 rulesPerPort[rule.getPortType()].remove(rule); 184 } 185 handleRuleDisabling(rule); 186 } 187 188 public void modifyRule( 189 int rid, 190 ATerm port, 191 ATerm cond, 192 ATerm act, 193 boolean enabled) { 194 int oldtype, newtype; 195 boolean wasEnabled; 196 197 DebugAdapterRule rule = rules[rid]; 198 199 debugMsg("oldrule" + rule); 200 201 oldtype = rule.getPortType(); 202 wasEnabled = rule.isEnabled(); 203 204 rule.modify(port, cond, act, enabled); 205 newtype = rule.getPortType(); 206 207 debugMsg("newrule" + rule); 208 209 if (wasEnabled && newtype != oldtype) { 210 synchronized (rulesPerPort[oldtype]) { 211 synchronized (rulesPerPort[newtype]) { 212 rulesPerPort[oldtype].remove(rule); 213 rulesPerPort[newtype].add(rule); 214 } 215 } 216 } 217 if (enabled) { 218 enableRule(rid); 219 } 220 } 221 222 public void deleteRule(int rid) { 223 DebugAdapterRule rule = rules[rid]; 224 int porttype = rule.getPortType(); 225 synchronized (rulesPerPort[porttype]) { 226 rulesPerPort[porttype].remove(rule); 227 } 228 rules[rid] = null; 229 handleRuleDestruction(rule); 230 } 231 232 public ATerm evaluate(ATerm act) { 233 int i; 234 235 switch (act.getType()) { 236 case ATerm.LIST : 237 //{ Evaluate all elements in a list 238 239 ATermList list = (ATermList) act; 240 List<ATerm> result = new ArrayList<ATerm>(); 241 while (!list.isEmpty()) { 242 ATerm elem = list.getFirst(); 243 ATerm val = evaluate(elem); 244 list = list.getNext(); 245 if (!val.equals(termTrue)) 246 result.add(elem); 247 } 248 if (result.isEmpty()) 249 return termTrue; 250 list = factory.makeList(); 251 for (int idx = result.size() - 1; idx >= 0; idx--) 252 list = factory.makeList(result.get(idx), list); 253 return list; 254 255 //} 256 257 case ATerm.APPL : 258 //{ Evaluate a function 259 260 ATermAppl appl = (ATermAppl) act; 261 if (appl.isQuoted()) { 262 return act; 263 } 264 String action = appl.getName(); 265 Class<?> myclass = getClass(); 266 String name = "action" + capitalize(action, true); 267 int arity = appl.getArity(); 268 269 boolean found = false; 270 271 do { 272 try { 273 Method method = 274 myclass.getDeclaredMethod(name, protos[arity]); 275 found = true; 276 Object[] args = new Object[arity]; 277 for (i = 0; i < arity; i++) { 278 args[i] = evaluate(appl.getArgument(i)); 279 } 280 debugMsg("invoking method: " + name); 281 return (ATerm) method.invoke(this, args); 282 } catch (NoSuchMethodException e) { 283 found = false; 284 } catch (InvocationTargetException e) { 285 return factory.make("error(\"the function " + name + " has thrown an exception\")"); 286 } catch (IllegalAccessException e) { 287 e.printStackTrace(); 288 found = false; 289 } 290 myclass = myclass.getSuperclass(); 291 } while (!found && myclass.getSuperclass() != null); 292 293 if (!found) { 294 return factory.make( 295 "error(\"unknown function: " 296 + action + " (" + name + ")" 297 + " with arity " 298 + arity 299 + "\")"); 300 } 301 default : 302 return act; 303 } 304 } 305 306 static private String capitalize(String str, boolean firstCap) { 307 StringBuffer name = new StringBuffer(); 308 for (int i = 0; i < str.length(); i++) { 309 if (str.charAt(i) == '-') 310 firstCap = true; 311 else { 312 if (firstCap) { 313 name.append(Character.toUpperCase(str.charAt(i))); 314 firstCap = false; 315 } else 316 name.append(str.charAt(i)); 317 } 318 } 319 return name.toString(); 320 } 321 322 public void handleRuleCreation(DebugAdapterRule rule){} 323 324 public void handleRuleDestruction(DebugAdapterRule rule){} 325 326 public void handleRuleEnabling(DebugAdapterRule rule){} 327 328 public void handleRuleDisabling(DebugAdapterRule rule){} 329 330 public void doBreak() { 331 changeExecState(STATE_STOPPED); 332 } 333 334 public void doResume() { 335 exec_state = STATE_RUNNING; 336 start_level = getStackLevel(); 337 } 338 339 public void doDisable(DebugAdapterRule rule) { 340 disableRule(rule.getId()); 341 List<Object> args = new ArrayList<Object>(); 342 args.add(new Integer(getPid())); 343 args.add(new Integer(rule.getId())); 344 adapter.postEvent( 345 factory.make("rule-disabled(proc(<str>),<int>)", args)); 346 } 347 348 public ATerm actionTrue() { 349 return termTrue; 350 } 351 352 public ATerm actionFalse() { 353 return termFalse; 354 } 355 356 public ATerm actionBreak() { 357 doBreak(); 358 return termTrue; 359 } 360 361 public ATerm actionResume() { 362 doResume(); 363 return termTrue; 364 } 365 366 public ATerm actionState() { 367 switch (exec_state) { 368 case STATE_RUNNING : 369 return termRunning; 370 case STATE_STOPPED : 371 return termStopped; 372 default : 373 return termUnknown; 374 } 375 } 376 377 public ATerm actionDisable() { 378 doDisable(current_rule); 379 return termTrue; 380 } 381 382 public ATerm actionHigherEqual(ATerm t1, ATerm t2) { 383 if (t1.getType() == ATerm.INT && t2.getType() == ATerm.INT) { 384 ATermInt i1 = (ATermInt) t1; 385 ATermInt i2 = (ATermInt) t2; 386 if (i1.getInt() >= i2.getInt()) 387 return termTrue; 388 } 389 return termFalse; 390 } 391 392 public ATerm actionEqual(ATerm t1, ATerm t2) { 393 return t1.isEqual(t2) ? termTrue : termFalse; 394 } 395 396 public ATerm actionStartLevel() { 397 return factory.parse("" + start_level); 398 } 399 400 public ATerm actionStackLevel() { 401 return factory.parse("" + getStackLevel()); 402 } 403 404 public abstract ATerm actionCpe(); 405 public abstract ATerm actionSourceVar(ATerm var, ATerm offset, ATerm line, ATerm col, ATerm dontknow); 406 407 public abstract int getStackLevel(); 408 }