diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/CommandQueue.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/CommandQueue.java new file mode 100644 index 00000000000..8293cf28999 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/CommandQueue.java @@ -0,0 +1,53 @@ +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ +package org.eclipse.cdt.debug.mi.core; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.cdt.debug.mi.core.command.Command; + +/** + * Simple thread-safe Queue implemetation. + */ +public class CommandQueue extends Queue{ + + + public CommandQueue() { + super(); + } + + public Command removeCommand(int id) { + //print("in removeCommand(" + id + ") - entering"); + synchronized (list) { + int size = list.size(); + for (int i = 0; i < size; i++) { + Command cmd = (Command)list.get(i); + int token = cmd.getToken(); + if (token == id) { + list.remove(cmd); + return cmd; + } + } + } + return null; + } + + public Command removeCommand() throws InterruptedException { + //print("in removeCommand() - entering"); + return (Command)removeItem(); + } + + public void addCommand(Command cmd) { + //print("in addCommand() - entering"); + addItem(cmd); + } + + private static void print(String msg) { + String name = Thread.currentThread().getName(); + System.out.println(name + ": " + msg); + } +} diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/EventThread.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/EventThread.java new file mode 100644 index 00000000000..10eef377795 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/EventThread.java @@ -0,0 +1,50 @@ +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +package org.eclipse.cdt.debug.mi.core; + +import java.io.IOException; + +import org.eclipse.cdt.debug.mi.core.event.MIEvent; + +/** + * Transmission command thread blocks on the command Queue + * and wake cmd are available and push them to gdb out channel. + */ +public class EventThread extends Thread { + + MISession session; + + public EventThread(MISession s) { + super("MI Event Thread"); + session = s; + } + + public void run () { + try { + while (true) { + MIEvent event = null; + Queue eventQueue = session.getEventQueue(); + // removeItem() will block until an item is available. + try { + event = (MIEvent)eventQueue.removeItem(); + } catch (InterruptedException e) { + // signal by the session of time to die. + if (session.getChannelOutputStream() == null) { + throw new IOException(); + } + //e.printStackTrace(); + } + try { + session.notifyObservers(event); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (IOException e) { + //e.printStackTrace(); + } + } +} diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIProcess.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIInferior.java similarity index 91% rename from debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIProcess.java rename to debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIInferior.java index 14ef224b30c..0254ff79350 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIProcess.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIInferior.java @@ -8,6 +8,7 @@ import org.eclipse.cdt.debug.mi.core.command.CLICommand; import org.eclipse.cdt.debug.mi.core.command.CommandFactory; import org.eclipse.cdt.debug.mi.core.command.MIExecAbort; import org.eclipse.cdt.debug.mi.core.command.MIGDBShowExitCode; +import org.eclipse.cdt.debug.mi.core.event.MIInferiorExitEvent; import org.eclipse.cdt.debug.mi.core.output.MIGDBShowExitCodeInfo; /** @@ -18,7 +19,7 @@ import org.eclipse.cdt.debug.mi.core.output.MIGDBShowExitCodeInfo; * To enable and disable the creation of type comments go to * Window>Preferences>Java>Code Generation. */ -public class MIProcess extends Process { +public class MIInferior extends Process { public final static int SUSPENDED = 1; public final static int RUNNING = 2; @@ -29,7 +30,7 @@ public class MIProcess extends Process { MISession session; OutputStream out; - MIProcess(MISession mi) { + MIInferior(MISession mi) { session = mi; out = new OutputStream() { StringBuffer buf = new StringBuffer(); @@ -39,6 +40,8 @@ public class MIProcess extends Process { flush(); } } + // Encapsulate the string sent to gdb in a fake command. + // and post it to the TxThread. public void flush() throws IOException { CLICommand cmd = new CLICommand(buf.toString()) { public void setToken(int token) { @@ -113,16 +116,13 @@ public class MIProcess extends Process { if (!isTerminated()) { CommandFactory factory = session.getCommandFactory(); MIExecAbort abort = factory.createMIExecAbort(); - CLICommand yes = new CLICommand("yes") { - public void setToken() { } - }; try { session.postCommand(abort); - session.postCommand(yes); + setTerminated(); + session.getRxThread().fireEvent(new MIInferiorExitEvent()); } catch (MIException e) { } } - // Do not wait for answer. } public synchronized boolean isSuspended() { diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java index 390e633532d..a3679b1a027 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java @@ -48,7 +48,7 @@ public class MIPlugin extends Plugin { } public ICDISession createCSession(String program) throws IOException { - String[]args = new String[]{"gdb", "--quiet", "-i", "mi", program}; + String[]args = new String[]{"gdb", "-q", "-i", "mi", program}; Process gdb = Runtime.getRuntime().exec(args); MISession session = createMISession(gdb.getInputStream(), gdb.getOutputStream()); /* diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MISession.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MISession.java index 683162692a3..1ebdf256b95 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MISession.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MISession.java @@ -13,6 +13,8 @@ import java.util.Observable; import org.eclipse.cdt.debug.mi.core.command.Command; import org.eclipse.cdt.debug.mi.core.command.CommandFactory; +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.output.MIOutput; import org.eclipse.cdt.debug.mi.core.output.MIParser; @@ -27,11 +29,13 @@ public class MISession extends Observable { InputStream inChannel; OutputStream outChannel; - Thread txThread; - Thread rxThread; + TxThread txThread; + RxThread rxThread; + EventThread eventThread; - Queue txQueue; - Queue rxQueue; + CommandQueue txQueue; + CommandQueue rxQueue; + Queue eventQueue; PipedInputStream miInPipe; PipedOutputStream miOutPipe; @@ -46,7 +50,7 @@ public class MISession extends Observable { long cmdTimeout = 10000; // 10 * 1000 (~ 10 secs); - MIProcess process; + MIInferior inferior; /** * Create the gdb session. @@ -59,12 +63,15 @@ public class MISession extends Observable { outChannel = o; factory = new CommandFactory(); parser = new MIParser(); - txQueue = new Queue(); - rxQueue = new Queue(); + txQueue = new CommandQueue(); + rxQueue = new CommandQueue(); + eventQueue = new Queue(); txThread = new TxThread(this); rxThread = new RxThread(this); + eventThread = new EventThread(this); txThread.start(); rxThread.start(); + eventThread.start(); try { miOutPipe = new PipedOutputStream(); @@ -76,7 +83,11 @@ public class MISession extends Observable { } catch (IOException e) { } - process = new MIProcess(this); + inferior = new MIInferior(this); + try { + postCommand(new MIGDBSet(new String[]{"confirm", "off"})); + } catch (MIException e) { + } } /** @@ -157,25 +168,35 @@ public class MISession extends Observable { public void postCommand(Command cmd, long timeout) throws MIException { MIPlugin.getDefault().debugLog(cmd.toString()); + + // Test if we in a sane state. if (!txThread.isAlive() || !rxThread.isAlive()) { throw new MIException("{R,T}xThread terminated"); } + txQueue.addCommand(cmd); + + // Wait for the response or timedout synchronized (cmd) { - // RxThread will set the MIOutput on the cmd - // when the response arrive. - while (cmd.getMIOutput() == null) { - try { - cmd.wait(timeout); - break; // Timeout or Notify - } catch (InterruptedException e) { + // Do not wait for command if time out is 0 + if (timeout > 0) { + // RxThread will set the MIOutput on the cmd + // when the response arrive. + while (cmd.getMIOutput() == null) { + try { + cmd.wait(timeout); + if (cmd.getMIOutput() == null) { + throw new MIException("Timedout"); + } + } catch (InterruptedException e) { + } } } } } - public MIProcess getMIProcess() { - return process; + public MIInferior getMIInferior() { + return inferior; } public boolean isTerminated() { @@ -187,9 +208,17 @@ public class MISession extends Observable { */ public void terminate() { - process.destroy(); + // Destroy any MI Inferior + inferior.destroy(); - // Closing the channel will kill the RxThread. + // send the exit. + try { + MIGDBExit exit = factory.createMIGDBExit(); + postCommand(exit); + } catch (MIException e) { + } + + // Explicitely close the channels try { inChannel.close(); } catch (IOException e) { @@ -200,9 +229,10 @@ public class MISession extends Observable { outChannel.close(); } catch (IOException e) { } - // This is __needed__ to stop the txThread. + // This is __needed__ to stop the txThread and eventThread. outChannel = null; + // Make sure all threads are gone. try { if (txThread.isAlive()) { txThread.interrupt(); @@ -218,6 +248,14 @@ public class MISession extends Observable { rxThread.join(); } catch (InterruptedException e) { } + + try { + if (eventThread.isAlive()) { + eventThread.interrupt(); + } + eventThread.join(); + } catch (InterruptedException e) { + } } /** @@ -241,14 +279,22 @@ public class MISession extends Observable { return logOutPipe; } - Queue getTxQueue() { + CommandQueue getTxQueue() { return txQueue; } - Queue getRxQueue() { + CommandQueue getRxQueue() { return rxQueue; } + Queue getEventQueue() { + return eventQueue; + } + + RxThread getRxThread() { + return rxThread; + } + InputStream getChannelInputStream() { return inChannel; } diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/Queue.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/Queue.java index 69b5c1ad65e..c7ccd86baa0 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/Queue.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/Queue.java @@ -8,65 +8,47 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -import org.eclipse.cdt.debug.mi.core.command.Command; - /** * Simple thread-safe Queue implemetation. */ public class Queue { - private List list; + protected List list; public Queue() { list = Collections.synchronizedList(new LinkedList()); } - public Command removeCommand(int id) { - //print("in removeCommand(" + id + ") - entering"); - synchronized (list) { - int size = list.size(); - for (int i = 0; i < size; i++) { - Command cmd = (Command)list.get(i); - int token = cmd.getToken(); - if (token == id) { - list.remove(cmd); - return cmd; - } - } - } - return null; - } - - public Command removeCommand() throws InterruptedException { - //print("in removeCommand() - entering"); + public Object removeItem() throws InterruptedException { + //print("in removeItem() - entering"); synchronized (list) { while (list.isEmpty()) { - //print("in removeCommand() - about to wait()"); + //print("in removeItem() - about to wait()"); list.wait(); - //print("in removeCommand() - done with wait()"); + //print("in removeItem() - done with wait()"); } // extract the new first cmd - Command cmd = (Command)list.remove(0); + Object item = list.remove(0); - //print("in removeCommand() - leaving"); - return cmd; + //print("in removeItem() - leaving"); + return item; } } - public void addCommand(Command cmd) { - //print("in addCommand() - entering"); + public void addItem(Object item) { + //print("in addItem() - entering"); synchronized (list) { // There will always be room to add to this List // because it expands as needed. - list.add(cmd); - //print("in addCommand - just added: '" + cmd + "'"); + list.add(item); + //print("in addItem - just added: '" + cmd + "'"); // After adding, notify any and all waiting // threads that the list has changed. list.notifyAll(); - //print("in addCommand() - just notified"); + //print("in addItem() - just notified"); } - //print("in addCommand() - leaving"); + //print("in addItem() - leaving"); } private static void print(String msg) { diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/RxThread.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/RxThread.java index 88d4f80c190..9d9657e2533 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/RxThread.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/RxThread.java @@ -18,7 +18,6 @@ import org.eclipse.cdt.debug.mi.core.command.MIExecNextInstruction; 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.event.EventThread; import org.eclipse.cdt.debug.mi.core.event.MIBreakpointEvent; import org.eclipse.cdt.debug.mi.core.event.MIEvent; import org.eclipse.cdt.debug.mi.core.event.MIExitEvent; @@ -68,30 +67,12 @@ public class RxThread extends Thread { while (true) { String line; while ((line = reader.readLine()) != null) { - // Testing on GNU/Linux where target stream output - // is entertwine with MI out, - // comment out the if/else below and just use: - // processMIOutput(line); - // at least for testing. - - // We accumulate until we see the gdb terminator. MIPlugin.getDefault().debugLog(line); - if (line.startsWith(MIOutput.terminator)) { - // discard termination - processMIOutput(buffer.toString()); - buffer = new StringBuffer(); - } else if (line.startsWith(MITargetStreamOutput.startTag)) { - // Process Target output immediately. - processMIOutput(line + "\n"); - } else { - buffer.append(line).append('\n'); - } + processMIOutput(line + "\n"); } } } catch (IOException e) { - MIEvent event = new MIExitEvent(); - Thread eventTread = new EventThread(session, new MIEvent[]{event}); - eventTread.start(); + fireEvent(new MIExitEvent()); //e.printStackTrace(); } } @@ -106,7 +87,7 @@ MIPlugin.getDefault().debugLog(line); MIOutput response = session.parse(buffer); if (response != null) { List list = new ArrayList(); - Queue rxQueue = session.getRxQueue(); + CommandQueue rxQueue = session.getRxQueue(); // Notify any command waiting for a ResultRecord. MIResultRecord rr = response.getMIResultRecord(); @@ -135,11 +116,11 @@ MIPlugin.getDefault().debugLog(line); } else { type = MIRunningEvent.CONTINUE; } - session.getMIProcess().setRunning(); + session.getMIInferior().setRunning(); MIEvent event = new MIRunningEvent(type); - fireEvents(new MIEvent[]{event}); + fireEvent(event); } else if ("exit".equals(state)) { - session.getMIProcess().setTerminated(); + session.getMIInferior().setTerminated(); } // Notify the waiting command. @@ -180,11 +161,12 @@ MIPlugin.getDefault().debugLog(line); void processMIOOBRecord(MIAsyncRecord async, List list) { if (async instanceof MIExecAsyncOutput) { MIExecAsyncOutput exec = (MIExecAsyncOutput)async; + MIEvent e = null; // Change of state. String state = exec.getAsyncClass(); if ("stopped".equals(state)) { - session.getMIProcess().setSuspended(); + session.getMIInferior().setSuspended(); } MIResult[] results = exec.getMIResults(); @@ -194,13 +176,22 @@ MIPlugin.getDefault().debugLog(line); if (var.equals("reason")) { if (val instanceof MIConst) { String reason = ((MIConst)val).getString(); - MIEvent e = createEvent(reason, exec); + e = createEvent(reason, exec); if (e != null) { list.add(e); } } } } + + // HACK: GDB for temporary breakpoints will not send the + // "reason" ??? Fake this as breakpoint-hit + if (e == null) { + e = createEvent("breakpoint-hit", exec); + if (e != null) { + list.add(e); + } + } } else if (async instanceof MIStatusAsyncOutput) { // Nothing done .. but what about +download?? } else if (async instanceof MINotifyAsyncOutput) { @@ -318,19 +309,25 @@ MIPlugin.getDefault().debugLog(line); event = new MIFunctionFinishedEvent(rr); } } else if ("exited-normally".equals(reason)) { - session.getMIProcess().setTerminated(); + session.getMIInferior().setTerminated(); event = new MIInferiorExitEvent(); } else if ("exited-signalled".equals(reason)) { - session.getMIProcess().setTerminated(); + session.getMIInferior().setTerminated(); + event = new MIInferiorExitEvent(); + } else if ("exited".equals(reason)) { + session.getMIInferior().setTerminated(); event = new MIInferiorExitEvent(); } return event; } public void fireEvents(MIEvent[] events) { - if (events.length > 0) { - Thread eventTread = new EventThread(session, events); - eventTread.start(); + for (int i = 0; i < events.length; i++) { + fireEvent(events[i]); } } + + public void fireEvent(MIEvent event) { + session.getEventQueue().addItem(event); + } } diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/TxThread.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/TxThread.java index fa82c213627..2c95a8b9a7e 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/TxThread.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/TxThread.java @@ -30,7 +30,7 @@ public class TxThread extends Thread { try { while (true) { Command cmd = null; - Queue txQueue = session.getTxQueue(); + CommandQueue txQueue = session.getTxQueue(); // removeCommand() will block until a command is available. try { cmd = txQueue.removeCommand(); @@ -54,7 +54,7 @@ public class TxThread extends Thread { // a valid token, this is to permit input(HACK!) // or commands that do not want to wait for responses. if (cmd.getToken() > 0) { - Queue rxQueue = session.getRxQueue(); + CommandQueue rxQueue = session.getRxQueue(); rxQueue.addCommand(cmd); } } diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/CTarget.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/CTarget.java index d8b6908ec2b..60754ad2e3c 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/CTarget.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/CTarget.java @@ -30,8 +30,10 @@ import org.eclipse.cdt.debug.mi.core.command.MIExecRun; 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.MITargetDetach; +import org.eclipse.cdt.debug.mi.core.command.MIThreadListIds; import org.eclipse.cdt.debug.mi.core.output.MIDataEvaluateExpressionInfo; import org.eclipse.cdt.debug.mi.core.output.MIInfo; +import org.eclipse.cdt.debug.mi.core.output.MIThreadListIdsInfo; /** */ @@ -57,6 +59,16 @@ public class CTarget implements ICDITarget { threadList.remove(cthread); } + boolean containsCThread(int id) { + for (int i = 0; i < threadList.size(); i++) { + CThread cthread = (CThread)threadList.get(i); + if (cthread.getId() == id) { + return true; + } + } + return false; + } + CThread[] getCThreads() { return (CThread[])threadList.toArray(new CThread[threadList.size()]); } @@ -109,7 +121,7 @@ public class CTarget implements ICDITarget { * @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#getProcess() */ public Process getProcess() { - return session.getMISession().getMIProcess(); + return session.getMISession().getMIInferior(); } /** @@ -144,7 +156,29 @@ public class CTarget implements ICDITarget { * @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#getThreads() */ public ICDIThread[] getThreads() throws CDIException { - return new ICDIThread[0]; + MISession mi = session.getMISession(); + CommandFactory factory = mi.getCommandFactory(); + MIThreadListIds tids = factory.createMIThreadListIds(); + try { + mi.postCommand(tids); + MIThreadListIdsInfo info = tids.getMIThreadListIdsInfo(); + int[] ids = info.getThreadIds(); + if (ids != null && ids.length > 0) { + for (int i = 0; i < ids.length; i++) { + if (! containsCThread(ids[i])) { + addCThread(new CThread(this, ids[i])); + } + } + } else { + // HACK create a dummy thread + if (threadList.size() == 0) { + addCThread(new CThread(this, 1)); + } + } + } catch (MIException e) { + throw new CDIException(e.toString()); + } + return (ICDIThread[])getCThreads(); } /** @@ -158,21 +192,21 @@ public class CTarget implements ICDITarget { * @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#isStepping() */ public boolean isStepping() { - return session.getMISession().getMIProcess().isRunning(); + return session.getMISession().getMIInferior().isRunning(); } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#isSuspended() */ public boolean isSuspended() { - return session.getMISession().getMIProcess().isSuspended(); + return session.getMISession().getMIInferior().isSuspended(); } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#isTerminated() */ public boolean isTerminated() { - return session.getMISession().getMIProcess().isTerminated(); + return session.getMISession().getMIInferior().isTerminated(); } /** @@ -198,7 +232,9 @@ public class CTarget implements ICDITarget { */ public void resume() throws CDIException { MISession mi = session.getMISession(); - if (mi.getMIProcess().isSuspended()) { + if (mi.getMIInferior().isRunning() || mi.getMIInferior().isStepping()) { + throw new CDIException("Inferior already running"); + } else if (mi.getMIInferior().isSuspended()) { CommandFactory factory = mi.getCommandFactory(); MIExecContinue cont = factory.createMIExecContinue(); try { @@ -210,8 +246,11 @@ public class CTarget implements ICDITarget { } catch (MIException e) { throw new CDIException(e.toString()); } + } else if (mi.getMIInferior().isTerminated()) { + restart(); } else { restart(); + //throw new CDIException("Unknow state"); } } @@ -309,7 +348,7 @@ public class CTarget implements ICDITarget { * @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#terminate() */ public void terminate() throws CDIException { - session.getMISession().getMIProcess().destroy(); + session.getMISession().getMIInferior().destroy(); } /** diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/CThread.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/CThread.java index 2efc155e6c2..05a1af12d69 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/CThread.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/CThread.java @@ -6,9 +6,9 @@ import org.eclipse.cdt.debug.core.cdi.model.ICDIThread; import org.eclipse.cdt.debug.mi.core.MIException; import org.eclipse.cdt.debug.mi.core.MISession; import org.eclipse.cdt.debug.mi.core.command.CommandFactory; -import org.eclipse.cdt.debug.mi.core.command.MIStackListFrames; +import org.eclipse.cdt.debug.mi.core.command.MIStackListArguments; import org.eclipse.cdt.debug.mi.core.output.MIFrame; -import org.eclipse.cdt.debug.mi.core.output.MIStackListFramesInfo; +import org.eclipse.cdt.debug.mi.core.output.MIStackListArgumentsInfo; /** * @author alain @@ -32,7 +32,7 @@ public class CThread extends CObject implements ICDIThread { } public String toString() { - return "thread-" + Integer.toString(id); + return Integer.toString(id); } /** @@ -48,10 +48,12 @@ public class CThread extends CObject implements ICDIThread { public ICDIStackFrame[] getStackFrames() throws CDIException { MISession mi = getCTarget().getCSession().getMISession(); CommandFactory factory = mi.getCommandFactory(); - MIStackListFrames frames = factory.createMIStackListFrames(); + //MIStackListFrames frames = factory.createMIStackListFrames(); + MIStackListArguments frames = factory.createMIStackListArguments(true); try { mi.postCommand(frames); - MIStackListFramesInfo info = frames.getMIStackListFramesInfo(); + //MIStackListFramesInfo info = frames.getMIStackListFramesInfo(); + MIStackListArgumentsInfo info = frames.getMIStackListArgumentsInfo(); if (info == null) { throw new CDIException("Timedout"); } diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/EventManager.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/EventManager.java index e79bd797c5c..97841a84810 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/EventManager.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/EventManager.java @@ -34,12 +34,10 @@ public class EventManager extends SessionObject implements ICDIEventManager { public CDIObserver(ICDIEventListener l) { listener = l; } - public void update(Observable o, Object args) { - MIEvent[] events = (MIEvent[])args; - for (int i = 0; i < events.length; i++) { - ICDIEvent cdiEvent = EventAdapter.getCDIEvent(getCSession(), events[i]); - listener.handleDebugEvent(cdiEvent); - } + public void update(Observable o, Object arg) { + MIEvent event = (MIEvent)arg; + ICDIEvent cdiEvent = EventAdapter.getCDIEvent(getCSession(), event); + listener.handleDebugEvent(cdiEvent); } } diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/Variable.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/Variable.java index 7fb1038c18e..17622f310bc 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/Variable.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/Variable.java @@ -34,14 +34,14 @@ public class Variable extends CObject implements ICDIVariable { * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#getTypeName() */ public String getTypeName() throws CDIException { - return null; + return ""; } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#getValue() */ public ICDIValue getValue() throws CDIException { - return null; + return new Value(getCTarget(), arg.getValue()); } /** diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/command/MIStackListArguments.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/command/MIStackListArguments.java index ea7c57f007d..2eca901b8cd 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/command/MIStackListArguments.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/command/MIStackListArguments.java @@ -49,6 +49,10 @@ public class MIStackListArguments extends MICommand setParameters(params); } + public MIStackListArgumentsInfo getMIStackListArgumentsInfo() throws MIException { + return (MIStackListArgumentsInfo)getMIInfo(); + } + public MIInfo getMIInfo() throws MIException { MIInfo info = null; MIOutput out = getMIOutput(); diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/command/MIThreadListIds.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/command/MIThreadListIds.java index 303ef97cc8b..3adbaa0e176 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/command/MIThreadListIds.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/command/MIThreadListIds.java @@ -25,6 +25,10 @@ public class MIThreadListIds extends MICommand super("-thread-list-ids"); } + public MIThreadListIdsInfo getMIThreadListIdsInfo() throws MIException { + return (MIThreadListIdsInfo)getMIInfo(); + } + public MIInfo getMIInfo() throws MIException { MIInfo info = null; MIOutput out = getMIOutput(); diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/event/EventThread.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/event/EventThread.java deleted file mode 100644 index 6ef742e79c8..00000000000 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/event/EventThread.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.eclipse.cdt.debug.mi.core.event; - -import org.eclipse.cdt.debug.mi.core.MISession; - -/* - * (c) Copyright QNX Software Systems Ltd. 2002. - * All Rights Reserved. - */ - -public class EventThread extends Thread { - - final MISession session; - final MIEvent[] events; - - public EventThread(MISession s, MIEvent[] evts) { - super("MI Event Thread"); - session = s; - events = evts; - setDaemon(true); - } - - /* - */ - public void run () { - session.notifyObservers(events); - } -} diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIDataReadMemoryInfo.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIDataReadMemoryInfo.java index 343d5fc9969..4d15e692029 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIDataReadMemoryInfo.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIDataReadMemoryInfo.java @@ -25,61 +25,38 @@ public class MIDataReadMemoryInfo extends MIInfo { public MIDataReadMemoryInfo(MIOutput rr) { super(rr); + parse(); } public long getAddress() { - if (memories == null) { - parse(); - } return addr; } public long getNumberBytes() { - if (memories == null) { - parse(); - } return numBytes; } public long getTotalBytes() { - if (memories == null) { - parse(); - } return totalBytes; } public long getNextRow() { - if (memories == null) { - parse(); - } return nextRow; } public long getPreviousRow() { - if (memories == null) { - parse(); - } return prevRow; } public long getNextPage() { - if (memories == null) { - parse(); - } return nextPage; } public long getPreviousPage() { - if (memories == null) { - parse(); - } return prevPage; } public MIMemory[] getMemories() { - if (memories == null) { - parse(); - } return memories; } /* diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIParser.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIParser.java index d57c8209ce5..17761014a96 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIParser.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIParser.java @@ -116,13 +116,13 @@ public class MIParser { token.delete(0, i); } - // Process ResultRecord | Out-Of-Band Records + // ResultRecord ||| Out-Of-Band Records if (token.length() > 0) { if (token.charAt(0) == '^') { token.deleteCharAt(0); rr = processMIResultRecord(token, id); } else if(token.toString().startsWith(MIOutput.terminator)) { - break; + //break; // Do nothing. } else { MIOOBRecord band = processMIOOBRecord(token, id); if (band != null) { @@ -131,15 +131,14 @@ public class MIParser { } } } - MIOOBRecord[] bands = - (MIOOBRecord[]) oobs.toArray(new MIOOBRecord[oobs.size()]); + MIOOBRecord[] bands = (MIOOBRecord[]) oobs.toArray(new MIOOBRecord[oobs.size()]); mi.setMIOOBRecords(bands); mi.setMIResultRecord(rr); return mi; } /** - * Assuming '^' was deleted. + * Assuming '^' was deleted from the Result Record. */ private MIResultRecord processMIResultRecord(StringBuffer buffer, int id) { MIResultRecord rr = new MIResultRecord(); @@ -174,6 +173,7 @@ public class MIParser { } /** + * Find OutOfBand Records depending on the starting token. */ private MIOOBRecord processMIOOBRecord(StringBuffer buffer, int id) { MIOOBRecord oob = null; @@ -235,7 +235,8 @@ public class MIParser { } /** - * Assuming that the usual leading comma was consume. + * Assuming that the usual leading comma was consumed. + * Extract the MI Result comma seperated responses. */ private MIResult[] processMIResults(StringBuffer buffer) { List aList = new ArrayList(); @@ -255,7 +256,7 @@ public class MIParser { /** * Construct the MIResult. Characters will be consume/delete - * has moving forward constructing the AST. + * moving forward constructing the AST. */ private MIResult processMIResult(StringBuffer buffer) { MIResult result = new MIResult(); @@ -353,6 +354,14 @@ public class MIParser { return list; } + /* + * MI C-String rather MICOnst values are enclose in double quotes + * and any double quotes or backslash in the string are escaped. + * Assuming the starting double quote was removed. + * This method will stop at the closing double quote remove the extra + * backslach escaping and return the string __without__ the enclosing double quotes + * The orignal StringBuffer will move forward. + */ private String translateCString(StringBuffer buffer) { boolean escape = false; boolean closingQuotes = false; diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIStackListArgumentsInfo.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIStackListArgumentsInfo.java index fba3a6ad9a7..d3d54bea793 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIStackListArgumentsInfo.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIStackListArgumentsInfo.java @@ -20,7 +20,7 @@ public class MIStackListArgumentsInfo extends MIInfo { super(out); } - public MIFrame[] getFrames() { + public MIFrame[] getMIFrames() { if (frames == null) { parse(); } diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIStackListFramesInfo.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIStackListFramesInfo.java index aee3fb433be..5cd4d081a49 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIStackListFramesInfo.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIStackListFramesInfo.java @@ -23,7 +23,7 @@ public class MIStackListFramesInfo extends MIInfo { if (frames == null) { parse(); } - return null; + return frames; } void parse() { diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIThreadSelectInfo.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIThreadSelectInfo.java index 289fcb05ed8..ae30caf579c 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIThreadSelectInfo.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIThreadSelectInfo.java @@ -14,19 +14,14 @@ public class MIThreadSelectInfo extends MIInfo { public MIThreadSelectInfo(MIOutput out) { super(out); + parse(); } public int getNewThreadId() { - if (frame == null) { - parse(); - } return threadId; } public MIFrame getFrame() { - if (frame == null) { - parse(); - } return frame; } diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIVarListChildrenInfo.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIVarListChildrenInfo.java index 545573b84cb..ad3838c39d7 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIVarListChildrenInfo.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/output/MIVarListChildrenInfo.java @@ -15,7 +15,7 @@ import java.util.List; */ public class MIVarListChildrenInfo extends MIInfo { - MIChild[] children = new MIChild[0]; + MIChild[] children; int numchild; public MIVarListChildrenInfo(MIOutput record) {