From dbd62a6ed46e48bf85f227e9060afa000401e5fd Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Thu, 11 Nov 2004 03:02:58 +0000 Subject: [PATCH] 2004-11-10 Alain Magloire Fix for PR 51113 and PR 66268 It allow more flexibility in the GDB console, for example when gdb require interactive questions. * mi/org/eclipse/cdt/debug/mi/core/CLIProcessor.java * mi/org/eclipse/cdt/debug/mi/core/MISession.java * mi/org/eclipse/cdt/debug/mi/core/RxThread.java * mi/org/eclipse/cdt/debug/mi/core/SessionProcess.java * mi/org/eclipse/cdt/debug/mi/core/TxThread.java * mi/org/eclipse/cdt/debug/core/command/MIGDBShowPrompt.java * mi/org/eclipse/cdt/debug/core/command/RawCommand.java * mi/org/eclipse/cdt/debug/core/output/MIOutput.java * mi/org/eclipse/cdt/debug/core/output/MIParser.java --- debug/org.eclipse.cdt.debug.mi.core/ChangeLog | 15 ++++++ .../cdt/debug/mi/core/CLIProcessor.java | 48 +++++++++++++++---- .../eclipse/cdt/debug/mi/core/MISession.java | 35 +++++++++++++- .../eclipse/cdt/debug/mi/core/RxThread.java | 36 ++++++++++++++ .../cdt/debug/mi/core/SessionProcess.java | 16 ++++++- .../eclipse/cdt/debug/mi/core/TxThread.java | 11 +++-- .../mi/core/command/MIGDBShowPrompt.java | 25 ++++++++++ .../cdt/debug/mi/core/command/RawCommand.java | 44 +++++++++++++++++ .../cdt/debug/mi/core/output/MIOutput.java | 1 - .../cdt/debug/mi/core/output/MIParser.java | 5 +- 10 files changed, 218 insertions(+), 18 deletions(-) create mode 100644 debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/command/MIGDBShowPrompt.java create mode 100644 debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/command/RawCommand.java diff --git a/debug/org.eclipse.cdt.debug.mi.core/ChangeLog b/debug/org.eclipse.cdt.debug.mi.core/ChangeLog index 4c060152481..4331b7cd0f6 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/ChangeLog +++ b/debug/org.eclipse.cdt.debug.mi.core/ChangeLog @@ -1,3 +1,18 @@ +2004-11-10 Alain Magloire + Fix for PR 51113 and PR 66268 + It allow more flexibility in the GDB console, for example + when gdb require interactive questions. + + * mi/org/eclipse/cdt/debug/mi/core/CLIProcessor.java + * mi/org/eclipse/cdt/debug/mi/core/MISession.java + * mi/org/eclipse/cdt/debug/mi/core/RxThread.java + * mi/org/eclipse/cdt/debug/mi/core/SessionProcess.java + * mi/org/eclipse/cdt/debug/mi/core/TxThread.java + * mi/org/eclipse/cdt/debug/core/command/MIGDBShowPrompt.java + * mi/org/eclipse/cdt/debug/core/command/RawCommand.java + * mi/org/eclipse/cdt/debug/core/output/MIOutput.java + * mi/org/eclipse/cdt/debug/core/output/MIParser.java + 2004-11-09 Alain Magloire Throw not implemented exception for exception breakpoint diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/CLIProcessor.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/CLIProcessor.java index 23d9628b3e7..7f00044f1e9 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/CLIProcessor.java +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/CLIProcessor.java @@ -35,19 +35,19 @@ public class CLIProcessor { * An attempt to discover the command type and * fire an event if necessary. */ - void process(CLICommand cmd) { + void processStateChanges(CLICommand cmd) { String operation = cmd.getOperation().trim(); - process(cmd.getToken(), operation); + processStateChanges(cmd.getToken(), operation); } - void process(MIInterpreterExecConsole exec) { + void processStateChanges(MIInterpreterExecConsole exec) { String[] operations = exec.getParameters(); if (operations != null && operations.length > 0) { - process(exec.getToken(), operations[0]); + processStateChanges(exec.getToken(), operations[0]); } } - void process(int token, String operation) { + void processStateChanges(int token, String operation) { // Get the command name. int indx = operation.indexOf(' '); if (indx != -1) { @@ -64,10 +64,40 @@ public class CLIProcessor { session.getMIInferior().setRunning(); MIEvent event = new MIRunningEvent(session, token, type); session.fireEvent(event); - } else if (isSettingBreakpoint(operation) || - isSettingWatchpoint(operation) || - isChangeBreakpoint(operation) || - isDeletingBreakpoint(operation)) { + } + } + + /** + * An attempt to discover the command type and + * fire an event if necessary. + */ + void processSettingChanges(CLICommand cmd) { + String operation = cmd.getOperation().trim(); + processSettingChanges(cmd.getToken(), operation); + } + + void processSettingChanges(MIInterpreterExecConsole exec) { + String[] operations = exec.getParameters(); + if (operations != null && operations.length > 0) { + processSettingChanges(exec.getToken(), operations[0]); + } + } + + void processSettingChanges(int token, String operation) { + // Get the command name. + int indx = operation.indexOf(' '); + if (indx != -1) { + operation = operation.substring(0, indx).trim(); + } else { + operation = operation.trim(); + } + + // Check the type of command + + if (isSettingBreakpoint(operation) || + isSettingWatchpoint(operation) || + isChangeBreakpoint(operation) || + isDeletingBreakpoint(operation)) { // We know something change, we just do not know what. // So the easiest way is to let the top layer handle it. session.fireEvent(new MIBreakpointChangedEvent(session, 0)); diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/MISession.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/MISession.java index b59e5781895..6c91aaff569 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/MISession.java +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/MISession.java @@ -24,9 +24,11 @@ import org.eclipse.cdt.debug.mi.core.command.CommandFactory; import org.eclipse.cdt.debug.mi.core.command.MIExecInterrupt; import org.eclipse.cdt.debug.mi.core.command.MIGDBExit; import org.eclipse.cdt.debug.mi.core.command.MIGDBSet; +import org.eclipse.cdt.debug.mi.core.command.MIGDBShowPrompt; import org.eclipse.cdt.debug.mi.core.command.MIInterpreterExecConsole; import org.eclipse.cdt.debug.mi.core.event.MIEvent; import org.eclipse.cdt.debug.mi.core.event.MIGDBExitEvent; +import org.eclipse.cdt.debug.mi.core.output.MIGDBShowInfo; import org.eclipse.cdt.debug.mi.core.output.MIOutput; import org.eclipse.cdt.debug.mi.core.output.MIParser; @@ -157,6 +159,7 @@ public class MISession extends Observable { postCommand(height, launchTimeout); height.getMIInfo(); + // Try to discover is "-interpreter-exec" is supported. try { MIInterpreterExecConsole echo = new MIInterpreterExecConsole("echo"); //$NON-NLS-1$ postCommand(echo, launchTimeout); @@ -166,6 +169,14 @@ public class MISession extends Observable { // } + // Get GDB's prompt + MIGDBShowPrompt prompt = new MIGDBShowPrompt(); + postCommand(prompt); + MIGDBShowInfo infoPrompt = prompt.getMIGDBShowInfo(); + String value = infoPrompt.getValue(); + if (value != null && value.length() > 0) { + parser.primaryPrompt = value.trim(); + } } catch (MIException exc) { // Kill the Transmition thread. if (txThread.isAlive()) { @@ -258,9 +269,17 @@ public class MISession extends Observable { } public boolean useExecConsole() { - return useInterpreterExecConsole; + return false; + //return useInterpreterExecConsole; } + public boolean inPrimaryPrompt() { + return rxThread.inPrimaryPrompt(); + } + + public boolean inSecondaryPrompt() { + return rxThread.inSecondaryPrompt(); + } /** * The debug session is a program being debug. */ @@ -306,6 +325,8 @@ public class MISession extends Observable { /** * Sends a command to gdb, and wait(timeout) for a response. + * if timeout < 0 the wait will be skipped. + * */ public void postCommand(Command cmd, long timeout) throws MIException { @@ -329,12 +350,24 @@ public class MISession extends Observable { postCommand0(cmd, timeout); } + /** + * if timeout < 0 the operation will not try to way for + * answer from gdb. + * + * @param cmd + * @param timeout + * @throws MIException + */ public synchronized void postCommand0(Command cmd, long timeout) throws MIException { // TRACING: print the command; MIPlugin.getDefault().debugLog(cmd.toString()); txQueue.addCommand(cmd); + // do not wait around the answer. + if (timeout < 0) { + return; + } // Wait for the response or timedout synchronized (cmd) { // RxThread will set the MIOutput on the cmd diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/RxThread.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/RxThread.java index 79f56417a1a..5596d2e808e 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/RxThread.java +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/RxThread.java @@ -17,6 +17,7 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.List; +import org.eclipse.cdt.debug.mi.core.command.CLICommand; import org.eclipse.cdt.debug.mi.core.command.Command; import org.eclipse.cdt.debug.mi.core.command.MIExecContinue; import org.eclipse.cdt.debug.mi.core.command.MIExecFinish; @@ -26,6 +27,7 @@ import org.eclipse.cdt.debug.mi.core.command.MIExecReturn; import org.eclipse.cdt.debug.mi.core.command.MIExecStep; import org.eclipse.cdt.debug.mi.core.command.MIExecStepInstruction; import org.eclipse.cdt.debug.mi.core.command.MIExecUntil; +import org.eclipse.cdt.debug.mi.core.command.MIInterpreterExecConsole; import org.eclipse.cdt.debug.mi.core.event.MIBreakpointHitEvent; import org.eclipse.cdt.debug.mi.core.event.MIErrorEvent; import org.eclipse.cdt.debug.mi.core.event.MIEvent; @@ -48,6 +50,7 @@ import org.eclipse.cdt.debug.mi.core.output.MILogStreamOutput; import org.eclipse.cdt.debug.mi.core.output.MINotifyAsyncOutput; import org.eclipse.cdt.debug.mi.core.output.MIOOBRecord; import org.eclipse.cdt.debug.mi.core.output.MIOutput; +import org.eclipse.cdt.debug.mi.core.output.MIParser; import org.eclipse.cdt.debug.mi.core.output.MIResult; import org.eclipse.cdt.debug.mi.core.output.MIResultRecord; import org.eclipse.cdt.debug.mi.core.output.MIStatusAsyncOutput; @@ -62,10 +65,13 @@ public class RxThread extends Thread { final MISession session; List oobList; + CLIProcessor cli; + int prompt = 1; // 1 --> Primary prompt "(gdb)"; 2 --> Secondary Prompt ">" public RxThread(MISession s) { super("MI RX Thread"); //$NON-NLS-1$ session = s; + cli = new CLIProcessor(session); oobList = new ArrayList(); } @@ -80,6 +86,7 @@ public class RxThread extends Thread { while ((line = reader.readLine()) != null) { // TRACING: print the output. MIPlugin.getDefault().debugLog(line); + setPrompt(line); processMIOutput(line + "\n"); //$NON-NLS-1$ } } catch (IOException e) { @@ -113,6 +120,26 @@ public class RxThread extends Thread { } } + void setPrompt(String line) { + line = line.trim(); + MIParser parser = session.getMIParser(); + if (line.equals(parser.primaryPrompt)) { + prompt = 1; + } else if (line.equals(parser.secondaryPrompt)) { + prompt = 2; + } else { + prompt = 0; + } + } + + public boolean inPrimaryPrompt() { + return prompt == 1; + } + + public boolean inSecondaryPrompt() { + return prompt == 2; + } + /** * Search for the command in the RxQueue, set the MIOutput * and notify() the other end. @@ -184,6 +211,13 @@ public class RxThread extends Thread { // Notify the waiting command. if (cmd != null) { + // Process the Command line to recognise patterns we may need to fire event. + if (cmd instanceof CLICommand) { + cli.processSettingChanges((CLICommand)cmd); + } else if (cmd instanceof MIInterpreterExecConsole) { + cli.processSettingChanges((MIInterpreterExecConsole)cmd); + } + synchronized (cmd) { // Set the accumulate console Stream response.setMIOOBRecords(oobRecords); @@ -283,6 +317,8 @@ public class RxThread extends Thread { if (console != null) { MIConsoleStreamOutput out = (MIConsoleStreamOutput) stream; String str = out.getString(); + // Process the console stream too. + setPrompt(str); if (str != null) { try { console.write(str.getBytes()); diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/SessionProcess.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/SessionProcess.java index 437944758b5..a0f9db79c97 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/SessionProcess.java +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/SessionProcess.java @@ -17,6 +17,7 @@ import java.io.OutputStream; import org.eclipse.cdt.debug.mi.core.command.CLICommand; import org.eclipse.cdt.debug.mi.core.command.Command; import org.eclipse.cdt.debug.mi.core.command.MIInterpreterExecConsole; +import org.eclipse.cdt.debug.mi.core.command.RawCommand; /** */ @@ -78,15 +79,26 @@ public class SessionProcess extends Process { String str = buf.toString().trim(); buf.setLength(0); Command cmd = null; + // 1- + // if We have the secondary prompt it means + // that GDB is waiting for more feedback, use a RawCommand + // 2- // Do not use the interpreterexec for stepping operation // the UI will fall out of step. - if (session.useExecConsole() && str.length() > 0 && !CLIProcessor.isSteppingOperation(str)) { + // 3- + // Normal Command Line Interface. + boolean secondary = session.inSecondaryPrompt(); + if (secondary) { + cmd = new RawCommand(str); + } else if (session.useExecConsole() && str.length() > 0 + && !CLIProcessor.isSteppingOperation(str)) { cmd = new MIInterpreterExecConsole(str); } else { cmd = new CLICommand(str); } try { - session.postCommand(cmd); + // Do not wait around for the answer. + session.postCommand(cmd, -1); } catch (MIException e) { //e.printStackTrace(); throw new IOException(e.getMessage()); diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/TxThread.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/TxThread.java index cfd6e1f5ba8..d112f7f6170 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/TxThread.java +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/TxThread.java @@ -17,6 +17,7 @@ import java.io.OutputStream; import org.eclipse.cdt.debug.mi.core.command.CLICommand; import org.eclipse.cdt.debug.mi.core.command.Command; import org.eclipse.cdt.debug.mi.core.command.MIInterpreterExecConsole; +import org.eclipse.cdt.debug.mi.core.command.RawCommand; /** * Transmission command thread blocks on the command Queue @@ -35,6 +36,8 @@ public class TxThread extends Thread { public void run () { try { + RxThread rxThread = session.getRxThread(); + // signal by the session of time to die. OutputStream out; while ((out = session.getChannelOutputStream()) != null) { @@ -53,7 +56,7 @@ public class TxThread extends Thread { if (str.length() > 0) { // Move to the RxQueue only if RxThread is alive. Thread rx = session.getRxThread(); - if (rx != null && rx.isAlive()) { + if (rx != null && rx.isAlive() && !(cmd instanceof RawCommand)) { CommandQueue rxQueue = session.getRxQueue(); rxQueue.addCommand(cmd); } else { @@ -65,11 +68,11 @@ public class TxThread extends Thread { // Process the Command line to recognise patterns we may need to fire event. if (cmd instanceof CLICommand) { - cli.process((CLICommand)cmd); + cli.processStateChanges((CLICommand)cmd); } else if (cmd instanceof MIInterpreterExecConsole) { - cli.process((MIInterpreterExecConsole)cmd); + cli.processStateChanges((MIInterpreterExecConsole)cmd); } - + // shove in the pipe if (out != null) { out.write(str.getBytes()); diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/command/MIGDBShowPrompt.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/command/MIGDBShowPrompt.java new file mode 100644 index 00000000000..33900013600 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/command/MIGDBShowPrompt.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.mi.core.command; + +/** + * -gdb-show prompt + */ +public class MIGDBShowPrompt extends MIGDBShow { + + /** + * @param params + */ + public MIGDBShowPrompt() { + super(new String[] { "prompt" }); //$NON-NLS-1$ + } +} diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/command/RawCommand.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/command/RawCommand.java new file mode 100644 index 00000000000..e41bd1109e0 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/command/RawCommand.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.mi.core.command; + +import org.eclipse.cdt.debug.mi.core.output.MIOutput; + +/** + */ +public class RawCommand extends Command { + + String fRaw; + + public RawCommand(String operation) { + fRaw = operation; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + if (fRaw == null) { + fRaw = "\n"; //$NON-NLS-1$; + } else if (! fRaw.endsWith("\n")) { + fRaw += "\n"; //$NON-NLS-1$ + } + return fRaw; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.mi.core.command.Command#getMIOutput() + */ + public MIOutput getMIOutput() { + return new MIOutput(); + } +} diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/output/MIOutput.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/output/MIOutput.java index 63cf77c9348..207cef0ced4 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/output/MIOutput.java +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/output/MIOutput.java @@ -15,7 +15,6 @@ package org.eclipse.cdt.debug.mi.core.output; */ public class MIOutput { - public static final String terminator = "(gdb)"; //$NON-NLS-1$ public static final MIOOBRecord[] nullOOBRecord = new MIOOBRecord[0]; MIResultRecord rr = null; MIOOBRecord[] oobs = nullOOBRecord; diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/output/MIParser.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/output/MIParser.java index 4801a8da309..1ce6d75b56d 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/output/MIParser.java +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/output/MIParser.java @@ -90,6 +90,9 @@ import java.util.StringTokenizer; */ public class MIParser { + public String primaryPrompt = "(gdb)"; //$NON-NLS-1$ + public String secondaryPrompt = ">"; //$NON-NLS-1$ + /** * Point of entry to create an AST for MI. * @@ -127,7 +130,7 @@ public class MIParser { if (token.charAt(0) == '^') { token.deleteCharAt(0); rr = processMIResultRecord(token, id); - } else if (token.toString().startsWith(MIOutput.terminator)) { + } else if (token.toString().startsWith(primaryPrompt)) { //break; // Do nothing. } else { MIOOBRecord band = processMIOOBRecord(token, id);