package mmrnmhrm.core.launch.debug;
import java.io.IOException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import melnorme.utilbox.misc.StringUtil;
import org.eclipse.cdt.dsf.mi.service.command.output.MIAsyncRecord;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOOBRecord;
import org.eclipse.cdt.dsf.mi.service.command.output.MIParser;
import org.eclipse.cdt.dsf.mi.service.command.output.MIParser.RecordType;
import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.core.model.IStreamsProxy;
public class GdbController implements IDebuggerHandler {
protected final IProcess gdbProcess;
protected final Process sp;
protected final IStreamsProxy streamsProxy;
protected final ScheduledExecutorService dispatcher;
protected final MIParser miParser;
protected final DeeDebugTarget deeDebugTarget;
public GdbController(IProcess gdbProcess, Process sp, DeeDebugTarget deeDebugTarget) {
this.gdbProcess = gdbProcess;
this.sp = sp;
this.streamsProxy = gdbProcess.getStreamsProxy();
this.deeDebugTarget = deeDebugTarget;
this.dispatcher = new ScheduledThreadPoolExecutor(1);
this.miParser = new MIParser();
// TODO: race condition here because we don't read all output since process start, some initial might be skipped
streamsProxy.getOutputStreamMonitor().addListener(new IStreamListener() {
@Override
public void streamAppended(String text, IStreamMonitor monitor) {
handleGdbOuput(text);
}
});
}
@Override
public void dispose() {
dispatcher.shutdown();
}
@Override
public void commandStartSession() {
dispatcher.submit(new Runnable() {
@Override
public void run() {
doStart();
}
});
}
@Override
public void commandSuspend() {
dispatcher.submit(new Runnable() {
@Override
public void run() {
doSuspend();
}
});
}
@Override
public void commandResume() {
dispatcher.submit(new Runnable() {
@Override
public void run() {
doResume();
}
});
}
protected void doStart() {
writeData("-exec-run --start\n");
}
protected void doResume() {
writeData("-exec-continue\n");
}
protected void doSuspend() {
writeData("-exec-interrupt\n");
}
protected void writeData(String string) {
try {
byte[] data = string.getBytes(StringUtil.ASCII); /*BUG here use UTF-8*/
sp.getOutputStream().write(data);
sp.getOutputStream().flush();
} catch (IOException ioe) {
// TODO: handle error
}
// try {
// streamsProxy.write("echo info source\n");
// } catch (IOException e) {
// DeeCore.log(e);
// }
}
protected final StringBuilder debuggerOutputBuffer = new StringBuilder();
protected void handleGdbOuput(String data) {
// Split output by line.
int eolIndex = data.indexOf('\n');
if(eolIndex == -1) {
debuggerOutputBuffer.append(data);
return;
}
debuggerOutputBuffer.append(data, 0, eolIndex + 1);
handleMIEvent(debuggerOutputBuffer.toString());
debuggerOutputBuffer.setLength(0);
data = data.substring(eolIndex+1);
handleGdbOuput(data);
}
protected void handleMIEvent(String miEventLine) {
RecordType recordType = miParser.getRecordType(miEventLine);
if(recordType == RecordType.ResultRecord) {
MIResultRecord miResultRecord = miParser.parseMIResultRecord(miEventLine);
} else if (recordType == RecordType.OOBRecord) {
MIOOBRecord miOOBRecord = miParser.parseMIOOBRecord(miEventLine);
if(miOOBRecord instanceof MIAsyncRecord) {
MIAsyncRecord miAsyncRecord = (MIAsyncRecord) miOOBRecord;
miAsyncRecord.getMIResults();
if(miAsyncRecord.getAsyncClass().equals("thread-created")) {
handleMIThreadCreated(miAsyncRecord);
} else if(miAsyncRecord.getAsyncClass().equals("thread-exited")) {
handleMIThreadDeleted(miAsyncRecord);
}
}
}
}
protected void handleMIThreadCreated(MIAsyncRecord miAsyncRecord) {
deeDebugTarget.createThread("1");
}
protected void handleMIThreadDeleted(MIAsyncRecord miAsyncRecord) {
deeDebugTarget.threads.remove("1");
}
}