blob: 5b531d9e522b329bf856e106bc7209ed6d7cad1c [file] [log] [blame]
/*
*(c) Copyright QNX Software Systems Ltd. 2002.
* All Rights Reserved.
*
*/
package org.eclipse.cdt.debug.mi.core.cdi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.cdt.debug.core.cdi.CDIException;
import org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager;
import org.eclipse.cdt.debug.core.cdi.ICDICatchEvent;
import org.eclipse.cdt.debug.core.cdi.ICDICondition;
import org.eclipse.cdt.debug.core.cdi.ICDILocation;
import org.eclipse.cdt.debug.core.cdi.ICDISharedLibraryManager;
import org.eclipse.cdt.debug.core.cdi.model.ICDIBreakpoint;
import org.eclipse.cdt.debug.core.cdi.model.ICDICatchpoint;
import org.eclipse.cdt.debug.core.cdi.model.ICDILocationBreakpoint;
import org.eclipse.cdt.debug.core.cdi.model.ICDITarget;
import org.eclipse.cdt.debug.core.cdi.model.ICDIWatchpoint;
import org.eclipse.cdt.debug.mi.core.MIException;
import org.eclipse.cdt.debug.mi.core.MISession;
import org.eclipse.cdt.debug.mi.core.cdi.model.Breakpoint;
import org.eclipse.cdt.debug.mi.core.cdi.model.Target;
import org.eclipse.cdt.debug.mi.core.cdi.model.Watchpoint;
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
import org.eclipse.cdt.debug.mi.core.command.MIBreakAfter;
import org.eclipse.cdt.debug.mi.core.command.MIBreakCondition;
import org.eclipse.cdt.debug.mi.core.command.MIBreakDelete;
import org.eclipse.cdt.debug.mi.core.command.MIBreakDisable;
import org.eclipse.cdt.debug.mi.core.command.MIBreakEnable;
import org.eclipse.cdt.debug.mi.core.command.MIBreakInsert;
import org.eclipse.cdt.debug.mi.core.command.MIBreakList;
import org.eclipse.cdt.debug.mi.core.command.MIBreakWatch;
import org.eclipse.cdt.debug.mi.core.event.MIBreakpointChangedEvent;
import org.eclipse.cdt.debug.mi.core.event.MIBreakpointCreatedEvent;
import org.eclipse.cdt.debug.mi.core.event.MIBreakpointDeletedEvent;
import org.eclipse.cdt.debug.mi.core.event.MIEvent;
import org.eclipse.cdt.debug.mi.core.output.MIBreakInsertInfo;
import org.eclipse.cdt.debug.mi.core.output.MIBreakListInfo;
import org.eclipse.cdt.debug.mi.core.output.MIBreakWatchInfo;
import org.eclipse.cdt.debug.mi.core.output.MIBreakpoint;
import org.eclipse.cdt.debug.mi.core.output.MIInfo;
/**
* Breakpoint Manager for the CDI interface.
*/
public class BreakpointManager extends SessionObject implements ICDIBreakpointManager {
List breakList;
List deferredList;
boolean allowInterrupt;
boolean autoupdate;
public BreakpointManager(Session session) {
super(session);
breakList = Collections.synchronizedList(new ArrayList());
deferredList = Collections.synchronizedList(new ArrayList());
allowInterrupt = true;
autoupdate = false;
}
public MIBreakpoint[] getMIBreakpoints() throws CDIException {
Session s = (Session)getSession();
CommandFactory factory = s.getMISession().getCommandFactory();
MIBreakList breakpointList = factory.createMIBreakList();
try {
s.getMISession().postCommand(breakpointList);
MIBreakListInfo info = breakpointList.getMIBreakListInfo();
if (info == null) {
throw new CDIException("No answer");
}
return info.getMIBreakpoints();
} catch (MIException e) {
throw new MI2CDIException(e);
}
}
boolean hasBreakpointChanged(Breakpoint point, MIBreakpoint miBreakpoint) {
MIBreakpoint miBreak = point.getMIBreakpoint();
return miBreak.isEnabled() != miBreakpoint.isEnabled() ||
!miBreak.getCondition().equals(miBreakpoint.getCondition()) ||
miBreak.getIgnoreCount() != miBreakpoint.getIgnoreCount();
}
public Breakpoint getBreakpoint(int number) {
Breakpoint[] bkpts = (Breakpoint[]) breakList.toArray(new Breakpoint[0]);
for (int i = 0; i < bkpts.length; i++) {
MIBreakpoint miBreak = bkpts[i].getMIBreakpoint();
if (miBreak.getNumber() == number) {
return bkpts[i];
}
}
return null;
}
public Watchpoint getWatchpoint(int number) {
return (Watchpoint)getBreakpoint(number);
}
boolean suspendInferior(ICDITarget target) throws CDIException {
boolean shouldRestart = false;
// Stop the program
if (allowInterrupt) {
if (target instanceof Target) {
Target ctarget = (Target)target;
// Disable events.
if (ctarget.isRunning()) {
ctarget.suspend();
shouldRestart = true;
}
} else if (!target.isSuspended()) {
target.suspend();
shouldRestart = true;
}
}
return shouldRestart;
}
void resumeInferior(ICDITarget target, boolean shouldRestart) throws CDIException {
if (shouldRestart) {
target.resume();
}
}
public void deleteBreakpoint (int no) {
Breakpoint[] points = (Breakpoint[]) breakList.toArray(new Breakpoint[0]);
for (int i = 0; i < points.length; i++) {
if (points[i].getMIBreakpoint().getNumber() == no) {
breakList.remove(points[i]);
break;
}
}
}
public void enableBreakpoint(ICDIBreakpoint breakpoint) throws CDIException {
int number = 0;
if (breakpoint instanceof Breakpoint
&& breakList.contains(breakpoint)) {
number = ((Breakpoint) breakpoint).getMIBreakpoint().getNumber();
} else {
throw new CDIException("Not a CDT breakpoint");
}
boolean state = suspendInferior(breakpoint.getTarget());
Session session = (Session)getSession();
CommandFactory factory = session.getMISession().getCommandFactory();
MIBreakEnable breakEnable = factory.createMIBreakEnable(new int[] { number });
try {
session.getMISession().postCommand(breakEnable);
MIInfo info = breakEnable.getMIInfo();
if (info == null) {
throw new CDIException("No answer");
}
} catch (MIException e) {
throw new MI2CDIException(e);
} finally {
// Resume the program and enable events.
resumeInferior(breakpoint.getTarget(), state);
}
((Breakpoint) breakpoint).getMIBreakpoint().setEnabled(true);
// Fire a changed Event.
MISession mi = session.getMISession();
mi.fireEvent(new MIBreakpointChangedEvent(((Breakpoint)breakpoint).getMIBreakpoint().getNumber()));
}
public void disableBreakpoint(ICDIBreakpoint breakpoint) throws CDIException {
int number = 0;
if (breakpoint instanceof Breakpoint
&& breakList.contains(breakpoint)) {
number = ((Breakpoint) breakpoint).getMIBreakpoint().getNumber();
} else {
throw new CDIException("Not a CDT breakpoint");
}
Session session = (Session)getSession();
boolean state = suspendInferior(breakpoint.getTarget());
CommandFactory factory = session.getMISession().getCommandFactory();
MIBreakDisable breakDisable =
factory.createMIBreakDisable(new int[] { number });
try {
session.getMISession().postCommand(breakDisable);
MIInfo info = breakDisable.getMIInfo();
if (info == null) {
throw new CDIException("No answer");
}
} catch (MIException e) {
throw new MI2CDIException(e);
} finally {
resumeInferior(breakpoint.getTarget(), state);
}
((Breakpoint) breakpoint).getMIBreakpoint().setEnabled(false);
// Fire a changed Event.
MISession mi = session.getMISession();
mi.fireEvent(new MIBreakpointChangedEvent(((Breakpoint)breakpoint).getMIBreakpoint().getNumber()));
}
public void setCondition(ICDIBreakpoint breakpoint, ICDICondition condition) throws CDIException {
int number = 0;
if (breakpoint instanceof Breakpoint
&& breakList.contains(breakpoint)) {
number = ((Breakpoint) breakpoint).getMIBreakpoint().getNumber();
} else {
throw new CDIException("Not a CDT breakpoint");
}
Session session = (Session)getSession();
boolean state = suspendInferior(breakpoint.getTarget());
CommandFactory factory = session.getMISession().getCommandFactory();
// reset the values to sane states.
String exprCond = condition.getExpression();
if (exprCond == null) {
exprCond = "";
}
int ignoreCount = condition.getIgnoreCount();
if (ignoreCount < 0) {
ignoreCount = 0;
}
try {
MIBreakCondition breakCondition =
factory.createMIBreakCondition(number, exprCond);
session.getMISession().postCommand(breakCondition);
MIInfo info = breakCondition.getMIInfo();
if (info == null) {
throw new CDIException("No answer");
}
MIBreakAfter breakAfter =
factory.createMIBreakAfter(number, ignoreCount);
session.getMISession().postCommand(breakAfter);
info = breakAfter.getMIInfo();
if (info == null) {
throw new CDIException("No answer");
}
} catch (MIException e) {
throw new MI2CDIException(e);
} finally {
resumeInferior(breakpoint.getTarget(), state);
}
// Fire a changed Event.
MISession mi = session.getMISession();
mi.fireEvent(new MIBreakpointChangedEvent(((Breakpoint)breakpoint).getMIBreakpoint().getNumber()));
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#update()
*/
public void update() throws CDIException {
MIBreakpoint[] newMIBreakpoints = getMIBreakpoints();
List eventList = new ArrayList(newMIBreakpoints.length);
for (int i = 0; i < newMIBreakpoints.length; i++) {
int no = newMIBreakpoints[i].getNumber();
Breakpoint bp = getBreakpoint(no);
if (bp != null) {
if (hasBreakpointChanged(bp, newMIBreakpoints[i])) {
// Fire ChangedEvent
bp.setMIBreakpoint(newMIBreakpoints[i]);
eventList.add(new MIBreakpointChangedEvent(no));
} else {
eventList.add(new MIBreakpointCreatedEvent(no));
}
} else {
// add the new breakpoint and fire CreatedEvent
if (newMIBreakpoints[i].isWatchpoint()) {
breakList.add(new Watchpoint(this, newMIBreakpoints[i]));
} else {
breakList.add(new Breakpoint(this, newMIBreakpoints[i]));
}
eventList.add(new MIBreakpointCreatedEvent(no));
}
}
// Check if any breakpoint was removed.
Breakpoint[] oldBreakpoints = (Breakpoint[]) breakList.toArray(new Breakpoint[0]);
for (int i = 0; i < oldBreakpoints.length; i++) {
boolean found = false;
int no = oldBreakpoints[i].getMIBreakpoint().getNumber();
for (int j = 0; j < newMIBreakpoints.length; j++) {
if (no == newMIBreakpoints[j].getNumber()) {
found = true;
break;
}
}
if (!found) {
// Fire destroyed Events.
eventList.add(new MIBreakpointDeletedEvent(no));
}
}
MISession mi = ((Session)getSession()).getMISession();
MIEvent[] events = (MIEvent[])eventList.toArray(new MIEvent[0]);
mi.fireEvents(events);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#allowProgramInterruption()
*/
public void allowProgramInterruption(boolean e) {
allowInterrupt = e;
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#deleteAllBreakpoints()
*/
public void deleteAllBreakpoints() throws CDIException {
deleteBreakpoints(getBreakpoints());
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#deleteBreakpoint(ICDIBreakpoint)
*/
public void deleteBreakpoint(ICDIBreakpoint breakpoint) throws CDIException {
deleteBreakpoints(new ICDIBreakpoint[] { breakpoint });
}
public void deleteFromDeferredList(Breakpoint bkpt) {
deferredList.remove(bkpt);
}
public void addToBreakpointList(Breakpoint bkpt) {
breakList.add(bkpt);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#deleteBreakpoints(ICDIBreakpoint[])
*/
public void deleteBreakpoints(ICDIBreakpoint[] breakpoints) throws CDIException {
int[] numbers = new int[breakpoints.length];
for (int i = 0; i < numbers.length; i++) {
if (breakpoints[i] instanceof Breakpoint
&& breakList.contains(breakpoints[i])) {
numbers[i] =
((Breakpoint) breakpoints[i]).getMIBreakpoint().getNumber();
} else {
throw new CDIException("Not a CDT breakpoint");
}
}
Session session = (Session)getSession();
boolean state = suspendInferior(session.getCurrentTarget());
CommandFactory factory = session.getMISession().getCommandFactory();
MIBreakDelete breakDelete = factory.createMIBreakDelete(numbers);
try {
session.getMISession().postCommand(breakDelete);
MIInfo info = breakDelete.getMIInfo();
if (info == null) {
throw new CDIException("No answer");
}
} catch (MIException e) {
throw new MI2CDIException(e);
} finally {
resumeInferior(session.getCurrentTarget(), state);
}
List eventList = new ArrayList(breakpoints.length);
for (int i = 0; i < breakpoints.length; i++) {
int no = ((Breakpoint)breakpoints[i]).getMIBreakpoint().getNumber();
eventList.add(new MIBreakpointDeletedEvent(no));
}
MISession mi = session.getMISession();
MIEvent[] events = (MIEvent[])eventList.toArray(new MIEvent[0]);
mi.fireEvents(events);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#getBreakpoints()
*/
public ICDIBreakpoint[] getBreakpoints() throws CDIException {
return (ICDIBreakpoint[]) breakList.toArray(new ICDIBreakpoint[0]);
}
public ICDIBreakpoint[] getDeferredBreakpoints() throws CDIException {
return (ICDIBreakpoint[]) deferredList.toArray(new ICDIBreakpoint[0]);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setCatchpoint(int, ICDICatchEvent, String, ICDICondition, boolean)
*/
public ICDICatchpoint setCatchpoint( int type, ICDICatchEvent event, String expression,
ICDICondition condition) throws CDIException {
throw new CDIException("Not Supported");
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setLocationBreakpoint(int, ICDILocation, ICDICondition, boolean, String)
*/
public ICDILocationBreakpoint setLocationBreakpoint(int type, ICDILocation location,
ICDICondition condition, String threadId) throws CDIException {
return setLocationBreakpoint(type, location, condition, threadId, false);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setLocationBreakpoint(int, ICDILocation, ICDICondition, boolean, String)
*/
public ICDILocationBreakpoint setLocationBreakpoint(int type, ICDILocation location,
ICDICondition condition, String threadId, boolean deferred) throws CDIException {
Breakpoint bkpt = new Breakpoint(this, type, location, condition, threadId);
try {
setLocationBreakpoint(bkpt);
breakList.add(bkpt);
// Fire a created Event.
Session session = (Session)getSession();
MISession mi = session.getMISession();
mi.fireEvent(new MIBreakpointCreatedEvent(bkpt.getMIBreakpoint().getNumber()));
} catch (CDIException e) {
if (!deferred) {
throw e;
} else {
Session session = (Session)getSession();
ICDISharedLibraryManager sharedMgr = session.getSharedLibraryManager();
if (sharedMgr instanceof SharedLibraryManager) {
SharedLibraryManager mgr = (SharedLibraryManager)sharedMgr;
if (mgr.isDeferredBreakpoint()) {
deferredList.add(bkpt);
} else {
throw e;
}
}
}
}
return bkpt;
}
MIBreakInsert createMIBreakInsert(Breakpoint bkpt) throws CDIException {
boolean hardware = bkpt.isHardware();
boolean temporary = bkpt.isTemporary();
String exprCond = null;
int ignoreCount = 0;
StringBuffer line = new StringBuffer();
if (bkpt.getCondition() != null) {
ICDICondition condition = bkpt.getCondition();
exprCond = condition.getExpression();
ignoreCount = condition.getIgnoreCount();
}
if (bkpt.getLocation() != null) {
ICDILocation location = bkpt.getLocation();
String file = location.getFile();
String function = location.getFunction();
if (file != null && file.length() > 0) {
line.append(file).append(':');
if (function != null && function.length() > 0) {
line.append(function);
} else {
line.append(location.getLineNumber());
}
} else if (function != null && function.length() > 0) {
line.append(function);
} else if (location.getLineNumber() != 0) {
line.append(location.getLineNumber());
} else {
line.append('*').append(location.getAddress());
}
}
Session session = (Session)getSession();
CommandFactory factory = session.getMISession().getCommandFactory();
return factory.createMIBreakInsert(temporary, hardware, exprCond, ignoreCount, line.toString());
}
public void setLocationBreakpoint (Breakpoint bkpt) throws CDIException {
Session session = (Session)getSession();
boolean state = suspendInferior(session.getCurrentTarget());
MIBreakInsert breakInsert = createMIBreakInsert(bkpt);
MIBreakpoint[] points = null;
try {
session.getMISession().postCommand(breakInsert);
MIBreakInsertInfo info = breakInsert.getMIBreakInsertInfo();
if (info == null) {
throw new CDIException("No answer");
}
points = info.getMIBreakpoints();
if (points == null || points.length == 0) {
throw new CDIException("Error parsing");
}
} catch (MIException e) {
throw new MI2CDIException(e);
} finally {
resumeInferior(session.getCurrentTarget(), state);
}
bkpt.setMIBreakpoint(points[0]);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setWatchpoint(int, int, String, ICDICondition, boolean)
*/
public ICDIWatchpoint setWatchpoint( int type, int watchType, String expression,
ICDICondition condition) throws CDIException {
boolean access = ( (watchType & ICDIWatchpoint.WRITE) == ICDIWatchpoint.WRITE &&
(watchType & ICDIWatchpoint.READ) == ICDIWatchpoint.READ );
boolean read = ( !((watchType & ICDIWatchpoint.WRITE) == ICDIWatchpoint.WRITE) &&
(watchType & ICDIWatchpoint.READ) == ICDIWatchpoint.READ );
Session session = (Session)getSession();
boolean state = suspendInferior(session.getCurrentTarget());
CommandFactory factory = session.getMISession().getCommandFactory();
MIBreakWatch breakWatch =
factory.createMIBreakWatch(access, read, expression);
MIBreakpoint[] points = null;
try {
session.getMISession().postCommand(breakWatch);
MIBreakWatchInfo info = breakWatch.getMIBreakWatchInfo();
points = info.getMIBreakpoints();
if (info == null) {
throw new CDIException("No answer");
}
if (points == null || points.length == 0) {
throw new CDIException("Parsing Error");
}
} catch (MIException e) {
throw new MI2CDIException(e);
} finally {
resumeInferior(session.getCurrentTarget(), state);
}
Watchpoint bkpt = new Watchpoint(this, points[0]);
breakList.add(bkpt);
// Fire a created Event.
MISession mi = session.getMISession();
mi.fireEvent(new MIBreakpointCreatedEvent(bkpt.getMIBreakpoint().getNumber()));
return bkpt;
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#createCondition(int, String)
*/
public ICDICondition createCondition(int ignoreCount, String expression) {
return new Condition(ignoreCount, expression);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#createLocation(String, String, int)
*/
public ICDILocation createLocation(String file, String function, int line) {
return new Location(file, function, line);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#createLocation(long)
*/
public ICDILocation createLocation(long address) {
return new Location(address);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#isAutoUpdate()
*/
public boolean isAutoUpdate() {
return autoupdate;
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIBreakpointManager#setAutoUpdate(boolean)
*/
public void setAutoUpdate(boolean update) {
autoupdate = update;
}
}