package xtc.lang.blink; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.lang.String.format; import xtc.tree.GNode; import xtc.tree.Token; import xtc.tree.Visitor; import xtc.lang.jeannie.Utilities; import xtc.lang.blink.CommandAstAnalyzer.Language; import xtc.lang.blink.CallStack.JavaCallFrame; import xtc.lang.blink.CallStack.NativeCallFrame; import xtc.lang.blink.SymbolMapper.SourceFileAndLine; import xtc.lang.blink.SymbolMapper.VariableRemapEntry; import xtc.lang.blink.Event.Java2NativeReturnEvent; import xtc.lang.blink.Event.JavaBreakPointHitEvent; import xtc.lang.blink.Event.JavaStepCompletionEvent; import xtc.lang.blink.Event.Native2JavaReturnEvent; import xtc.lang.blink.Event.NativeBreakPointHitEvent; import xtc.lang.blink.Event.NativeStepCompletionEvent; import xtc.lang.blink.Event.SessionFinishRequestEvent; /** * The user command line interpreter. * * @author Byeongcheol Lee */ public final class CommandInterpreter extends Visitor { /* Type equivalences for Primitive Types in JNI and Java. */ private static Map<String,String> c2jPrimitiveType = new HashMap<String,String>(); private static Map<String,String> j2cPrimitiveType = new HashMap<String,String>(); static { c2jPrimitiveType.put("jboolean", "jboolean"); c2jPrimitiveType.put("jbyte", "jbyte"); c2jPrimitiveType.put("jshort", "jshort"); c2jPrimitiveType.put("jchar", "jchar"); c2jPrimitiveType.put("jint", "jint"); c2jPrimitiveType.put("jlong", "jlong"); c2jPrimitiveType.put("jfloat", "jfloat"); c2jPrimitiveType.put("jdouble", "jdouble"); c2jPrimitiveType.put("int", "jint"); // implicit conversion j2cPrimitiveType.put("boolean", "jboolean"); j2cPrimitiveType.put("byte", "jbyte"); j2cPrimitiveType.put("short", "jshort"); j2cPrimitiveType.put("char", "jchar"); j2cPrimitiveType.put("int", "jint"); j2cPrimitiveType.put("long", "jlong"); j2cPrimitiveType.put("float", "jfloat"); j2cPrimitiveType.put("double", "jdouble"); } /* Opaque reference types in JNI. */ private static Set<String> opaqueJNITypes = new HashSet<String>(); static { opaqueJNITypes.add("jobject"); opaqueJNITypes.add("jclass"); opaqueJNITypes.add("jthrowable"); opaqueJNITypes.add("jstring"); opaqueJNITypes.add("jarray"); opaqueJNITypes.add("jbooleanArray"); opaqueJNITypes.add("jbyteArray"); opaqueJNITypes.add("jcharArray"); opaqueJNITypes.add("jshortArray"); opaqueJNITypes.add("jintArray"); opaqueJNITypes.add("jlongArray"); opaqueJNITypes.add("jfloatArray"); opaqueJNITypes.add("jdoubleArray"); opaqueJNITypes.add("jobjectArray"); } /** Generate an expression. */ private static String gen(String format, Object ... args) { return format(format, args); } private static String getJNITypeNameFromJavaTypeName(String javaTypeName) { if (j2cPrimitiveType.containsKey(javaTypeName)) { return j2cPrimitiveType.get(javaTypeName); } else { return "jobject"; } } /** Getter the language property of the node. */ private static Language getLanguage(final GNode n) { return (Language) n.getProperty("language"); } private static String mapToJNIType(String ctypeName) { if (c2jPrimitiveType.containsKey(ctypeName)) { return c2jPrimitiveType.get(ctypeName); } else if (opaqueJNITypes.contains(ctypeName)) { return "jobject"; } else { return null; } } /** join a number of expressions by inserting a string between them. */ private static String join(String s, Object[] exprs) { StringBuilder sb = new StringBuilder(); for(int i = 0; i < exprs.length;i++) { if (i == 0) { sb.append(exprs[i]); } else { sb.append(s).append(exprs[i]); } } return sb.toString(); } /** * The blink debugger for the communication with jdb, gdb and the Blink Debug * Agent (BDA). */ private final Blink dbg; /** The break point manager. */ private final BreakPointManager breakpointManager; /** The Jeannie symbol remapper. */ private final SymbolMapper jeannieSymbolRemapper; /** The current context for debugging. */ private DebuggerContext debuggerContext; /** * Constructor. * * @param dbg The blink debugger. * @param breakpointManager The break point manager. */ CommandInterpreter(final Blink dbg, BreakPointManager breakpointManager) { this.dbg = dbg; this.breakpointManager = breakpointManager; this.jeannieSymbolRemapper = new SymbolMapper(); } /** * Transfer data from C to Java. * * @param cexpr The C expression. * @return The Java convenience variable. */ private String backtick_c2j(String cexpr) throws Exception { DebuggerContext c = ensureDebuggerContext(); NativeCallFrame nframe = c.getCurrentNativeFrame(); dbg.ensureGDBContext(); String cTypeName= dbg.ndb.whatis(nframe, cexpr); String jniTypeName = mapToJNIType(cTypeName); if (jniTypeName == null) { throw new Exception(format( "A '%s' value cannot be transferred from C to Java", cTypeName)); } String cExpression = gen("bda_cv_set_%s(%s)", jniTypeName, cexpr); String vjid = dbg.ndb.eval(nframe, cExpression); dbg.ensureJDBContext(); String jv = dbg.jdb.getConvenienceVariableExpression(vjid); return jv; } /** * Transfer data from Java to C. * * @param jexpr The Java expression. * @return A C convenience variable. */ private String backtick_j2c(String jexpr) throws Exception { DebuggerContext c = ensureDebuggerContext(); JavaCallFrame jframe = c.getCurrentJavaFrame(); NativeCallFrame nframe = c.getCurrentNativeFrame(); dbg.ensureJDBContext(); String vjid = dbg.jdb.set_j(jframe, jexpr); String javaTypeName= dbg.jdb.getConvenienceVariableTypeName(vjid);; String jniTypeName = getJNITypeNameFromJavaTypeName(javaTypeName); dbg.ensureGDBContext(); String cv = dbg.ndb.getNewCTmpVarIdentifier(); String cexpression = gen("bda_cv_get_%s(%s)", jniTypeName, vjid); dbg.ndb.setVariable(nframe, cv, cexpression); return cv; } /** Clear the current debugger context. */ private final void clearDebuggerContext() { debuggerContext = null; } /** Ensure the debugger context is available at the return of this method. */ private final DebuggerContext ensureDebuggerContext() throws Exception { if (debuggerContext != null ) { return debuggerContext; } dbg.ensurePureContext(); CallStack callStack = CallStack.extractCallStack(dbg, jeannieSymbolRemapper); debuggerContext = new DebuggerContext(callStack); return debuggerContext; } /** Implement BlinkEventSource. */ public String getEventSourceName() { return "CommandRunner"; } /** * Evaluate a C expression. * * This is one of the six Blink expression evaluation primitives. * @param cexpr The expression. * @return The result of evaluating the <String> */ private String print_c(String cexpr) throws Exception { DebuggerContext c = ensureDebuggerContext(); NativeCallFrame nframe = c.getCurrentNativeFrame(); dbg.ensureGDBContext(); String result = dbg.ndb.eval(nframe, cexpr); return result; } /** * Evaluate a Java expression. * * @param jexpr The expression. * @return The string representation of the result value. */ private String print_j(String jexpr) throws Exception { dbg.ensureJDBContext(); DebuggerContext c = ensureDebuggerContext(); JavaCallFrame jf = c.getCurrentJavaFrame(); String result = dbg.jdb.print(jf, jexpr); return result; } /** Finish the expression evaluation. */ private final void resetConvenienceVariables() { try { dbg.ensureJDBContext(); dbg.jdb.resetConvenienceVariables(); dbg.ensureGDBContext(); dbg.ndb.resetConvenienceVariables(); } catch (Exception e) { dbg.err("could not successfully clean JDB temp varaibles.\n"); } } /** Visit the AbstractDeclarator expression node. */ public final String visitAbstractDeclarator(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("%s %s", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(1))); } /** Visit the addictive expression node. */ public final String visitAdditiveExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit an AddressExpression = Expression. */ public final String visitAddressExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String expr = (String)dispatch(n.getNode(0)); return gen("(& %s)", expr); } /** Visit Arguments = Expression*. */ public final String[] visitArguments(final GNode n) { assert getLanguage(n) == Language.JAVA; String[] args = new String[n.size()]; for (int i=0; i<n.size(); i++) args[i] = (String)dispatch(n.getNode(i)); return args; } /** Visit the ArrayDeclarator expression node. */ public final String visitArrayDeclarator(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("( %s [ %s ] )", (String) dispatch(n.getNode(0)), (String) dispatch(n.getNode(1))); } /** Visit the ArrayInitializer expression node. */ public final String visitArrayInitializer(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** * Visit an AssignmentExpression = Expression ("=" / "+=" / "-=" / "*=" / "/=" * / "%=" / "<<=" / ">>=" / "&=" / "^=" / "|=") Expression. */ public final String visitAssignmentExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; // mark the LHS is the l-value expression generator. String expr0 = (String)dispatch(n.getNode(0)); String operator = n.getString(1); String expr1 = (String)dispatch(n.getNode(2)); return gen("(%s %s %s)", expr0, operator, expr1); } /** Visit the AutoSpecifier expression node. */ public final String visitAutoSpecifier(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("auto"); } /** Visit the BasicCastExpression expression node. */ public final String visitBasicCastExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the bitwise and expression node. */ public final String visitBitwiseAndExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit the bitwise negation expression node. */ public final String visitBitwiseNegationExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String operand = (String)dispatch(n.getNode(0)); return gen("(~ %s)", operand); } /** Visit the bitwise and expression node. */ public final String visitBitwiseOrExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit the bitwise xor expression node. */ public final String visitBitwiseXorExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit the Bool expression node. */ public final String visitBool(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("_Bool"); } /** Visit the BooleanLiteral expression node. */ public final String visitBooleanLiteral(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit a BreakClassCommand = QualifiedIdentifier LineNumber. */ public final void visitBreakClassCommand(final GNode n) { String className = n.getNode(0).getString(0); int lineNumber = Integer.parseInt( n.getString(1)); breakpointManager.setJavaBreakPoint(className, lineNumber); dbg.ensurePureContext(); } /** Visit a BreakClassCommand = QualifiedIdentifier. */ public final void visitBreakClassMethodCommand(final GNode n) { String classAndMethod= Utilities.qualifiedIdentifierToString(n.getGeneric(0)); Pattern p = Pattern.compile("^(.+)\\.([^\\.]+)$"); Matcher m = p.matcher(classAndMethod); if (m.matches()) { String cname = m.group(1); String mname = m.group(2); breakpointManager.setJavaBreakPoint(cname, mname); dbg.ensurePureContext(); } else { dbg.err("can not recognize as <class>.<method>\n"); } } /** Visit a BreakFileCommand = FileName LineNumber. */ public final void visitBreakFileCommand(final GNode n) { String fileName = n.getString(0); int lineNumber = Integer.parseInt(n.getString(1)); try { breakpointManager.setNativeBreakpoint(fileName, lineNumber); } catch(Exception e) { dbg.err("Can not set breakpoint."); } dbg.ensurePureContext(); } /** Visit a BreakFunctionCommand = Identifier. */ public final void visitBreakFunctionCommand(final GNode n) { String identifier = n.getString(0); try { breakpointManager.setNativeBreakpoint(identifier); } catch(Exception e) { dbg.err("Can not set breakpoint."); } dbg.ensurePureContext(); } /** Visit a C2jCommand = (no children). */ public final void visitC2jCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } dbg.c2j(); } /** Visit a CallExpression = [Expression] null MethodName Arguments. */ public String visitCallExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; String recv = (String) dispatch(n.getNode(0)); String meth = n.getString(2); String[] args = (String[]) dispatch(n.getNode(3)); return gen("(%s.%s(%s))", recv, meth, join(",",args)); } /** Visit the cast expression node. */ public final String visitCastExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; return gen("((%s)%s)", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(1))); } /** Visit the Char expression node. */ public final String visitChar(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("char"); } /** Visit the CharacterConstant expression node. */ public final String visitCharacterConstant(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return n.getString(0); } /** Visit the CharacterLiteral expression node. */ public final String visitCharacterLiteral(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit a CInJavaExpression = C.UnaryExpression. */ public final String visitCInJavaExpression(final GNode n)throws Exception { return backtick_c2j((String)dispatch(n.getNode(0))); } /** Visit the ClassLiteralExpression expression node. */ public final String visitClassLiteralExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the CommaExpression expression node. */ public final String visitCommaExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String[] exprs= new String[n.size()]; for (int i=0; i< n.size(); i++) { exprs[i] = (String)dispatch(n.getNode(i)); } return gen("%s", join(",", exprs)); } /** Visit the ConcreteDimensions expression node. */ public final String visitConcreteDimensions(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the ConditionalExpression expression node. */ public final String visitConditionalExpression(final GNode n) throws Exception { return gen("(%s ? %s : %s)", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(1)), (String)dispatch(n.getNode(2))); } /** Visit the ConstantQualifier expression node. */ public final String visitConstantQualifier(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("%s", n.getString(0)); } /** Visit a ContinueCommand = (no children). */ public final void visitContinueCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } clearDebuggerContext(); dbg.cont(); } /** Visit the DeclarationSpecifiers expression node. */ public final String visitDeclarationSpecifiers(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String[] specs = new String[n.size()]; for(int i = 0;i < specs.length;i++) { specs[i] = (String)dispatch(n.getNode(i)); } return gen("%s", join(" ", specs)); } /** Visit the Declarator expression node. */ public final String visitDeclarator(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the Declarators expression node. */ public final String visitDeclarators(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit a DeleteCommand = IntegerLiteral. */ public final void visitDeleteCommand(final GNode n) { int id = Integer.parseInt(n.getNode(0).getString(0)); breakpointManager.clearBreakpoint(id); dbg.ensurePureContext(); } /** Visit the Dimensions expression node. */ public final String visitDimensions(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the DirectAbstractDeclarator expression node. */ public final String visitDirectAbstractDeclarator(final GNode n) throws Exception { assert getLanguage(n) == Language.C; if (n.get(0) == null) { if (("[").equals(n.get(1))) { if (n.get(2) == null) { return gen("[]"); } else { return gen("[%s]", (String)dispatch(n.getNode(2))); } } else { return gen("(%s)", (String)dispatch(n.getNode(2))); } } else { if (("[").equals(n.get(1))) { if (n.get(2) == null) { return gen("%s []", (String)dispatch(n.getNode(0))); } else { return gen("%s [%s]", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(2))); } } else { return gen("%s (%s)", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(2))); } } } /** Visit a DirectComponentSelection = Expression String. */ public final String visitDirectComponentSelection(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String expr = (String)dispatch(n.getNode(0)); String comp = n.getString(1); return gen("(%s.%s)", expr, comp); } /** Visit the Double expression node. */ public final String visitDouble(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("double"); } /** Visit a DownCommand = IntegerLiteral. */ public final void visitDownCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } int steps = Integer.parseInt( n.getNode(0).getString(0)); try { ensureDebuggerContext(); debuggerContext.windStack(dbg, steps); } catch (Exception e) { dbg.err("could not perform up\n"); } finally { dbg.ensurePureContext(); } } /** Visit the EnumerationTypeReference expression node. */ public final String visitEnumerationTypeReference(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("enum %s", n.getString(1)); } /** Visit a EqualityExpression = Expression ("==" / "!=") Expression. */ public final String visitEqualityExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String expr0 = (String) dispatch(n.getNode(0)); String operator = n.getString(1); String expr1 = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", expr0, operator, expr1); } /** Visit a ExitCommand = (no children). */ public final void visitExitCommand(final GNode n) { dbg.ensurePureContext(); dbg.exit(); } /** * Visit a Expression = Expression ("=" / "+=" / "-=" / "*=" / "/=" / "&=" * / "|=" / "^=" / "%=" / "<<=" / ">>=" / ">>>=") * Expression. */ public final String visitExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; String lhs = (String)dispatch(n.getNode(0)); String op = n.getString(1); String rhs = (String)dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit ExpressionList = Expression+. */ public final String visitExpressionList(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String[] exprs= new String[n.size()]; for (int i=0; i<n.size(); i++) { exprs[i] = (String)dispatch(n.getNode(i)); } return gen("%s", join(",", exprs)); } /** Visit the Float expression node. */ public final String visitFloat(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("float"); } /** Visit the FloatingConstant expression node. */ public final String visitFloatingConstant(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(%s)", n.getString(0)); } /** Visit the FloatingPointLiteral expression node. */ public final String visitFloatingPointLiteral(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit a FunctionCall = Expression [ExpressionList]. */ public final String visitFunctionCall(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String exprFunc = (String)dispatch(n.getNode(0)); String args = n.getNode(1) == null ? "" : (String)dispatch(n.getNode(1)); return gen("(%s(%s))", exprFunc, args); } /** Visit the FunctionDeclarator expression node. */ public final String visitFunctionDeclarator(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("%s (%s)", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(1))); } /** Visit a GdbCommand = RestOfLine. */ public final void visitGdbCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.out("gdb is not activated yet.\n"); return; } String cmd = n.getString(0); try { String msg = dbg.ndb.runCommand(cmd); dbg.out("%s", msg); } catch (Exception e) { dbg.err("can not successfully native debugger command"); } } /** Visit a HelpCommand = (no children). */ public final void visitHelpCommand(final GNode n) { dbg.help(); dbg.ensurePureContext(); } /** Visit the IdentifierList expression node. */ public final String visitIdentifierList(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String[] exprs= new String[n.size()]; for (int i=0; i< n.size(); i++) { exprs[i] = Token.cast(n.get(i)); } return gen("%s", join(", ", exprs)); } public final String visitIndirectComponentSelection(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String e = (String)dispatch(n.getNode(0)); String field = n.getString(1); return gen("(%s->%s)", e, field); } /** Visit an IndirectionExpression = Expression. */ public final String visitIndirectionExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String expr = (String)dispatch(n.getNode(0)); return gen("(*%s)", expr); } /** Visit a InfoBreakCommand = (no children). */ public final void visitInfoBreakCommand(final GNode n) { breakpointManager.showUserBreakPointList(); dbg.ensurePureContext(); } /** Visit a InfoWatchCommand = (no children). */ public final void visitInfoWatchCommand(final GNode n) { assert false : "not yet implemented"; } /** Visit an InitJCommand = (no children). */ public final void visitInitJCommand(final GNode n) throws IOException { dbg.initj(); dbg.ensurePureContext(); } /** Visit the InstanceOfExpression expression node. */ public final String visitInstanceOfExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the InstantiatedType expression node. */ public final String visitInstantiatedType(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the Int expression node. */ public final String visitInt(final GNode n) throws Exception { assert getLanguage(n) == Language.C; assert false: "TBI"; return null; } /** Visit an IntegerConstant = String. */ public final String visitIntegerConstant(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(%s)", n.getString(0)); } /** Visit an IntegerLiteral = String. */ public final String visitIntegerLiteral(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; return gen("(%s)", n.getString(0)); } /** Visit a J2cCommand = (no children). */ public final void visitJ2cCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } dbg.j2c(); } /** Visit a JavaInStringession = Java.UnaryExpression. */ public final String visitJavaInCExpression(final GNode n) throws Exception { return backtick_j2c((String)dispatch(n.getNode(0))); } /** Visit a JdbCommand = RestOfLine. */ public final void visitJdbCommand(final GNode n) { String cmd = n.getString(0); try { String msg = dbg.jdb.runCommand(cmd); dbg.out("%s", msg); } catch (Exception e) { dbg.err("can not successfully run the jdb command"); } } /** Visit a JRetCommand = (no children). */ public final void visitJRetCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } dbg.jret(); } /** Visit a ListCommand = (no children). */ public final void visitListCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } try { ensureDebuggerContext(); debuggerContext.showSourceCode(dbg); } catch(Exception e) { dbg.err("could not perform the list command.\n"); } finally { dbg.ensurePureContext(); } } /** Visit a LocalsCommand = (no children). */ public final void visitLocalsCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } try { ensureDebuggerContext(); debuggerContext.showLocals(dbg, jeannieSymbolRemapper); } catch(Exception e) { dbg.err("could not perform list command.\n"); } finally { dbg.ensurePureContext(); } } /** Visit the LogicalAndExpression expression node. */ public final String visitLogicalAndExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit the LogicalNegationExpression expression node. */ public final String visitLogicalNegationExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; return gen("(! %s)", (String)dispatch(n.getNode(0))); } /** Visit the LogicalOrExpression expression node. */ public final String visitLogicalOrExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit the Long expression node. */ public final String visitLong(final GNode n) throws Exception { assert getLanguage(n) == Language.C; assert false: "TBI"; return null; } /** Visit a MetaVariable = Identifier. */ public final String visitMetaVariable(final GNode n) throws Exception { assert false : "not implemented yet"; return null; } /** Visit the MultiplicativeExpression expression node. */ public final String visitMultiplicativeExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit the NewArrayExpression expression node. */ public final String visitNewArrayExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the NewClassExpression expression node. */ public final String visitNewClassExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit a NextCommand = (no children). */ public final void visitNextCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } try { clearDebuggerContext(); Event e = dbg.next(); if (e instanceof NativeStepCompletionEvent || e instanceof JavaStepCompletionEvent || e instanceof Java2NativeReturnEvent || e instanceof Native2JavaReturnEvent) { SourceFileAndLine loc = dbg.getCurrentSourceLevelLocation(); String line = dbg.getCurrentSourceLine(); assert loc != null : "step must be completed at the source line"; dbg.out("Step completed: %s\n%s\n", loc, line); } else if ( e instanceof NativeBreakPointHitEvent) { EventLoop.reportEvent(dbg, (NativeBreakPointHitEvent)e); } else if ( e instanceof JavaBreakPointHitEvent) { EventLoop.reportEvent(dbg, (JavaBreakPointHitEvent)e); } else { assert false: "unrecognized event during stepping :" + e; } } catch (Exception e) { dbg.err("could not correctly perform the next command.\n"); } } /** Visit an NullLiteral = (no children). */ public final String visitNullLiteral(final GNode n) throws Exception{ assert getLanguage(n) == Language.JAVA; return gen("(%s)", "null"); } /** Visit the ParameterDeclaration expression node. */ public final String visitParameterDeclaration(final GNode n) throws Exception { assert getLanguage(n) == Language.C; if (n.get(1) == null) { return gen("%s", (String)dispatch(n.getNode(0))); } else { return gen("%s %s", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(1))); } } /** Visit the ParameterList expression node. */ public final String visitParameterList(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String[] exprs= new String[n.size()]; for (int i=0; i<n.size(); i++) { exprs[i] = (String)dispatch(n.getNode(i)); } return gen("%s", join(",", exprs)); } /** Visit the ParameterTypeList expression node. */ public final String visitParameterTypeList(final GNode n) throws Exception { assert getLanguage(n) == Language.C; if (n.get(1) == null) { return gen("%s", (String)dispatch(n.getNode(0))); } else { return gen("%s, ...", (String)dispatch(n.getNode(0))); } } /** Visit the Pointer expression node. */ public final String visitPointer(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("* %s %s", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(1))); } /** Visit the PointerDeclarator expression node. */ public final String visitPointerDeclarator(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("* %s %s", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(1))); } /** Visit the PostdecrementExpression expression node. */ public final String visitPostdecrementExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(%s--)", (String)dispatch(n.getNode(0))); } /** Visit the PostfixExpression expression node. */ public final String visitPostfixExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the PostincrementExpression expression node. */ public final String visitPostincrementExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(%s++)", (String)dispatch(n.getNode(0))); } /** Visit the PredecrementExpression expression node. */ public final String visitPredecrementExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(--%s)", (String)dispatch(n.getNode(0))); } /** Visit the PreincrementExpression expression node. */ public final String visitPreincrementExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(++%s)", (String)dispatch(n.getNode(0))); } /** Visit a PrimaryIdentifier = String. */ public String visitPrimaryIdentifier(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String idName = (String)n.get(0); //try id remapping for the Jeannie frame. ensureDebuggerContext(); SourceFileAndLine loc = debuggerContext.getCurrentLocation(); VariableRemapEntry idRemap = jeannieSymbolRemapper.lookUpVariableRemap(idName, loc .getSourceFile(), loc.getSourceLine()); String idExpr = null; if (idRemap != null) { idExpr = idRemap.targetLanguageExpression(); } if (idExpr == null) { idExpr = idName; } return gen("(%s)", idExpr); } /** Visit the PrimitiveType expression node. */ public final String visitPrimitiveType(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit a PrintCExpressionCommand = C.Expression. */ public final void visitPrintCExpressionCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } try { breakpointManager.freezeActiveBreakPoints(); Object obj = dispatch(n.getNode(0)); dbg.out("====> %s\n", print_c((String)obj)); } catch(Exception e) { dbg.err("could not correctly print the final result\n"); } finally { breakpointManager.unfreezeAllBreakpoints(); resetConvenienceVariables(); dbg.ensurePureContext(); } } /** Visit a PrintJavaExpressionCommand = Java.Expression. */ public final void visitPrintJavaExpressionCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } try { breakpointManager.freezeActiveBreakPoints(); Object obj = dispatch(n.getNode(0)); if (obj == null) {return;} dbg.out("=====> %s\n", print_j((String)obj)); } catch(Exception e) { dbg.err("could not correctly print the final result\n"); } finally { breakpointManager.unfreezeAllBreakpoints(); resetConvenienceVariables(); dbg.ensurePureContext(); } } /** Visit a QualifiedIdentifier = Identifier+. */ public final String visitQualifiedIdentifier(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; return gen("%s", Utilities.qualifiedIdentifierToString(n)); } /** Visit the RelationalExpression expression node. */ public final String visitRelationalExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit a NextCommand = (no children). */ public final void visitRunCommand(final GNode n) { dbg.run(); } /** Visit a SelectionExpression = Expression Identifier. */ public final String visitSelectionExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; return gen("(%s.%s)", ((String)dispatch(n.getNode(0))), n.getString(1)); } /** Visit the ShiftExpression expression node. */ public final String visitShiftExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String lhs = (String) dispatch(n.getNode(0)); String op = (String) (n.get(1)); String rhs = (String) dispatch(n.getNode(2)); return gen("(%s %s %s)", lhs, op, rhs); } /** Visit the Short expression node. */ public final String visitShort(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("short"); } /** Visit the Signed expression node. */ public final String visitSigned(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("%s", n.getString(0)); } /** Visit the SimpleDeclarator expression node. */ public final String visitSimpleDeclarator(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return n.getString(0); } /** Visit the SizeofExpression expression node. */ public final String visitSizeofExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(sizeof(%s))", (String)dispatch(n.getNode(0))); } /** Visit the SpecifierQualifierList expression node. */ public final String visitSpecifierQualifierList(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String[] specs = new String[n.size()]; for(int i = 0;i < specs.length;i++) { specs[i] = (String)dispatch(n.getNode(i)); } return gen("%s", join(" ", specs)); } /** Visit a StatCommand = (no children). */ public final void visitStatCommand(final GNode n) { dbg.out("control: %s\n", dbg.getDebugControlStatus()); } /** Visit a StepCommand = (no children). */ public final void visitStepCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } try { clearDebuggerContext(); dbg.step(); SourceFileAndLine loc = dbg.getCurrentSourceLevelLocation(); String line = dbg.getCurrentSourceLine(); assert loc != null : "step must be completed at the source line"; dbg.out("Step completed: %s\n%s\n", loc, line); } catch(Exception e) { dbg.err("could not sucessfully perform stepping\n"); } } /** Visit an StringConstant = String. */ public final String visitStringConstant(final GNode n) throws Exception { assert getLanguage(n) == Language.C; assert n.size() == 1; return gen("(%s)", n.getString(0)); } /** Visit an StringLiteral = String. */ public final String visitStringLiteral(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; return gen("(%s)",n.getString(0)); } /** Visit the StructureTypeReference expression node. */ public final String visitStructureTypeReference(final GNode n) throws Exception { assert getLanguage(n) == Language.C; assert n.get(0) == null; return gen("struct %s", n.getString(1)); } /** Visit a SubscriptExpression = Expression Expression. */ public final String visitSubscriptExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C || getLanguage(n) == Language.JAVA; String exprArray = (String) dispatch(n.getNode(0)); String exprIndex = (String) dispatch(n.getNode(1)); return gen("(%s[%s])", exprArray, exprIndex); } /** Visit the SuperExpression expression node. */ public final String visitSuperExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit a ThisExpression = [Expression]. */ public final void visitThisExpression(final GNode n) { assert getLanguage(n) == Language.JAVA; assert false : "The Blink debugger does not support" + "qualified this in Java expression."; } /** Visit the Type expression node. */ public final String visitType(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the TypeArguments expression node. */ public final String visitTypeArguments(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the TypedefName expression node. */ public final String visitTypedefName(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("%s", n.getString(0)); } /** Visit the TypeInstantiation expression node. */ public final String visitTypeInstantiation(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the TypeName expression node. */ public final String visitTypeName(final GNode n) throws Exception { assert getLanguage(n) == Language.C; if (n.get(1) == null) { return gen("%s", (String)dispatch(n.getNode(0))); } else { return gen("%s %s", (String)dispatch(n.getNode(0)), (String)dispatch(n.getNode(1))); } } /** Visit the TypeParameter expression node. */ public final String visitTypeParameter(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the TypeParameters expression node. */ public final String visitTypeParameters(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the TypeQualifierList expression node. */ public final String visitTypeQualifierList(final GNode n) throws Exception { assert getLanguage(n) == Language.C; String[] specs = new String[n.size()]; for(int i = 0;i < specs.length;i++) { specs[i] = (String)dispatch(n.getNode(i)); } return gen("%s", join(" ", specs)); } /** Visit the UnaryExpression expression node. */ public final String visitUnaryExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the UnaryMinusExpression expression node. */ public final String visitUnaryMinusExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(-%s)", (String)dispatch(n.getNode(0))); } /** Visit the UnaryPlusExpression expression node. */ public final String visitUnaryPlusExpression(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("(+%s)", (String)dispatch(n.getNode(0))); } /** Visit the UnionTypeReference expression node. */ public final String visitUnionTypeReference(final GNode n) throws Exception { assert getLanguage(n) == Language.C; assert n.get(0) == null; return gen("struct %s", n.getString(1)); } /** Visit the Unsigned expression node. */ public final String visitUnsigned(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("unsigned"); } /** Visit an UpCommand = IntegerLiteral. */ public final void visitUpCommand(final GNode n) { int steps = Integer.parseInt( n.getNode(0).getString(0)); try { ensureDebuggerContext(); debuggerContext.unWindStack(dbg, steps); } catch (Exception e) { dbg.err("could not perform up\n"); } finally { dbg.ensurePureContext(); } } /** Visit the VoidType expression node. */ public final String visitVoidType(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the VoidTypeSpecifier expression node. */ public final String visitVoidTypeSpecifier(final GNode n) throws Exception { assert getLanguage(n) == Language.C; return gen("void"); } /** Visit a WatchCExpressionCommand = C.Expression. */ public final void visitWatchCExpressionCommand(final GNode n) { assert false : "not yet implemented"; } /** Visit a WatchJavaFieldCommand = [WatchKind] QualifiedIdentifier. */ public final void visitWatchJavaFieldCommand(final GNode n) { assert false : "not yet implemented"; } /** Visit a WhereCommand = (no children). */ public final void visitWhereCommand(final GNode n) { if (!dbg.IsNativeDebuggerAttached()) { dbg.err("Blink is not initialized to run this command\n"); return; } try { ensureDebuggerContext(); debuggerContext.showWhere(dbg); } catch(Exception e) { dbg.err("could not perform where command.\n"); } finally { dbg.ensurePureContext(); } } /** Visit the Wildcard expression node. */ public final String visitWildcard(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } /** Visit the WildcardBound expression node. */ public final String visitWildcardBound(final GNode n) throws Exception { assert getLanguage(n) == Language.JAVA; assert false: "TBI"; return null; } }