mirror of
https://github.com/oliverschmidt/contiki.git
synced 2024-11-19 03:05:14 +00:00
reworked MspCodeWatcher plugin: using jsyntaxpane to display Contiki code, using tabs instead of splitpanes, easier to
configure watch-/breakpoints, lots of bug fixes and minor improvements
This commit is contained in:
parent
2e583c733e
commit
7cfa8e28d3
@ -31,26 +31,32 @@
|
|||||||
|
|
||||||
package se.sics.cooja.mspmote.plugins;
|
package se.sics.cooja.mspmote.plugins;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.Action;
|
||||||
|
import javax.swing.JColorChooser;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.JSeparator;
|
||||||
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
import javax.swing.table.TableCellEditor;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import se.sics.cooja.GUI;
|
import se.sics.cooja.GUI;
|
||||||
import se.sics.cooja.Mote;
|
import se.sics.cooja.Watchpoint;
|
||||||
import se.sics.cooja.MoteType;
|
import se.sics.cooja.WatchpointMote;
|
||||||
import se.sics.cooja.Simulation;
|
|
||||||
import se.sics.cooja.mspmote.MspMote;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a set of breakpoints.
|
* Displays a set of breakpoints.
|
||||||
@ -60,27 +66,27 @@ import se.sics.cooja.mspmote.MspMote;
|
|||||||
public class BreakpointsUI extends JPanel {
|
public class BreakpointsUI extends JPanel {
|
||||||
private static Logger logger = Logger.getLogger(BreakpointsUI.class);
|
private static Logger logger = Logger.getLogger(BreakpointsUI.class);
|
||||||
|
|
||||||
private static final int COLUMN_INFO = 0;
|
private static final int COLUMN_ADDRESS = 0;
|
||||||
private static final int COLUMN_ADDRESS = 1;
|
private static final int COLUMN_FILELINE = 1;
|
||||||
private static final int COLUMN_FILELINE = 2;
|
private static final int COLUMN_INFO = 2;
|
||||||
private static final int COLUMN_STOP = 3;
|
private static final int COLUMN_STOP = 3;
|
||||||
private static final int COLUMN_REMOVE = 4;
|
|
||||||
|
|
||||||
private static final String[] COLUMN_NAMES = {
|
private static final String[] COLUMN_NAMES = {
|
||||||
"Info",
|
|
||||||
"Address",
|
"Address",
|
||||||
"File",
|
"Source",
|
||||||
"Stop",
|
"Info",
|
||||||
"Remove"
|
"Stops simulation"
|
||||||
};
|
};
|
||||||
|
|
||||||
private MspBreakpointContainer breakpoints = null;
|
private WatchpointMote mote;
|
||||||
|
private MspCodeWatcher codeWatcher;
|
||||||
private JTable table = null;
|
private JTable table = null;
|
||||||
|
|
||||||
private MspBreakpoint popupBreakpoint = null;
|
private Watchpoint selectedWatchpoint = null;
|
||||||
|
|
||||||
public BreakpointsUI(MspBreakpointContainer breakpoints, final MspCodeWatcher codeWatcher) {
|
public BreakpointsUI(WatchpointMote mote, final MspCodeWatcher codeWatcher) {
|
||||||
this.breakpoints = breakpoints;
|
this.mote = mote;
|
||||||
|
this.codeWatcher = codeWatcher;
|
||||||
|
|
||||||
/* Breakpoints table */
|
/* Breakpoints table */
|
||||||
table = new JTable(tableModel) {
|
table = new JTable(tableModel) {
|
||||||
@ -93,15 +99,20 @@ public class BreakpointsUI extends JPanel {
|
|||||||
int realColumnIndex = table.convertColumnIndexToModel(colIndex);
|
int realColumnIndex = table.convertColumnIndexToModel(colIndex);
|
||||||
|
|
||||||
if (realColumnIndex == COLUMN_FILELINE) {
|
if (realColumnIndex == COLUMN_FILELINE) {
|
||||||
MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints();
|
Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints();
|
||||||
if (rowIndex < 0 || rowIndex >= allBreakpoints.length) {
|
if (rowIndex < 0 || rowIndex >= allBreakpoints.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
File file = allBreakpoints[rowIndex].getCodeFile();
|
Watchpoint watchpoint = allBreakpoints[rowIndex];
|
||||||
|
File file = watchpoint.getCodeFile();
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
return null;
|
return String.format("[unknown @ 0x%04x]", watchpoint.getExecutableAddress());
|
||||||
}
|
}
|
||||||
return file.getPath() + ":" + allBreakpoints[rowIndex].getLineNumber();
|
Integer line = watchpoint.getLineNumber();
|
||||||
|
if (line == null) {
|
||||||
|
return file.getPath() + ":?";
|
||||||
|
}
|
||||||
|
return file.getPath() + ":" + line;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realColumnIndex == COLUMN_INFO) {
|
if (realColumnIndex == COLUMN_INFO) {
|
||||||
@ -111,53 +122,41 @@ public class BreakpointsUI extends JPanel {
|
|||||||
if (realColumnIndex == COLUMN_STOP) {
|
if (realColumnIndex == COLUMN_STOP) {
|
||||||
return "Indicates whether the watchpoint will stop the simulation when triggered";
|
return "Indicates whether the watchpoint will stop the simulation when triggered";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realColumnIndex == COLUMN_REMOVE) {
|
|
||||||
return "Remove breakpoint from this mote only. (Right-click for more options)";
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
table.getColumnModel().getColumn(COLUMN_INFO).setCellRenderer(new DefaultTableCellRenderer() {
|
||||||
table.getColumnModel().getColumn(COLUMN_ADDRESS).setPreferredWidth(60); /* XXX */
|
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||||
table.getColumnModel().getColumn(COLUMN_ADDRESS).setMaxWidth(60);
|
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
table.getColumnModel().getColumn(COLUMN_INFO).setPreferredWidth(60);
|
Component c = super.getTableCellRendererComponent(
|
||||||
table.getColumnModel().getColumn(COLUMN_INFO).setMaxWidth(60);
|
table, value, isSelected, hasFocus, row, column);
|
||||||
table.getColumnModel().getColumn(COLUMN_INFO).setCellRenderer(
|
if (column != COLUMN_INFO) {
|
||||||
new DefaultTableCellRenderer() {
|
return c;
|
||||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
}
|
||||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
|
||||||
Component c = super.getTableCellRendererComponent(
|
Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints();
|
||||||
table, value, isSelected, hasFocus, row, column);
|
if (row < 0 || row >= allBreakpoints.length) {
|
||||||
if (column != COLUMN_INFO) {
|
return c;
|
||||||
return c;
|
}
|
||||||
}
|
Watchpoint breakpoint = allBreakpoints[row];
|
||||||
|
if (breakpoint.getColor() == null) {
|
||||||
MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints();
|
return c;
|
||||||
if (row < 0 || row >= allBreakpoints.length) {
|
}
|
||||||
return c;
|
|
||||||
}
|
/* Use watchpoint color */
|
||||||
MspBreakpoint breakpoint = allBreakpoints[row];
|
c.setBackground(Color.WHITE);
|
||||||
if (breakpoint.getColor() == null) {
|
c.setForeground(breakpoint.getColor());
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
/* Use watchpoint color */
|
|
||||||
c.setForeground(breakpoint.getColor());
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
table.getColumnModel().getColumn(COLUMN_STOP).setPreferredWidth(60);
|
|
||||||
table.getColumnModel().getColumn(COLUMN_STOP).setMaxWidth(60);
|
|
||||||
table.getColumnModel().getColumn(COLUMN_REMOVE).setPreferredWidth(60);
|
|
||||||
table.getColumnModel().getColumn(COLUMN_REMOVE).setMaxWidth(60);
|
|
||||||
|
|
||||||
/* Popup menu: register on all motes */
|
/* Popup menu: register on all motes */
|
||||||
final JPopupMenu popupMenu = new JPopupMenu();
|
final JPopupMenu popupMenu = new JPopupMenu();
|
||||||
popupMenu.add(new JMenuItem(addToMoteTypeAction));
|
popupMenu.add(new JMenuItem(gotoCodeAction));
|
||||||
popupMenu.add(new JMenuItem(delFromMoteTypeAction));
|
popupMenu.add(new JSeparator());
|
||||||
|
popupMenu.add(new JMenuItem(removeWatchpointAction));
|
||||||
|
popupMenu.add(new JMenuItem(configureWatchpointAction));
|
||||||
|
|
||||||
/* Show source file on breakpoint mouse click */
|
|
||||||
table.addMouseListener(new MouseAdapter() {
|
table.addMouseListener(new MouseAdapter() {
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
java.awt.Point p = e.getPoint();
|
java.awt.Point p = e.getPoint();
|
||||||
@ -167,63 +166,32 @@ public class BreakpointsUI extends JPanel {
|
|||||||
|
|
||||||
if (realColumnIndex != COLUMN_ADDRESS
|
if (realColumnIndex != COLUMN_ADDRESS
|
||||||
&& realColumnIndex != COLUMN_FILELINE
|
&& realColumnIndex != COLUMN_FILELINE
|
||||||
&& realColumnIndex != COLUMN_REMOVE
|
|
||||||
&& realColumnIndex != COLUMN_INFO) {
|
&& realColumnIndex != COLUMN_INFO) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints();
|
Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints();
|
||||||
if (rowIndex < 0 || rowIndex >= allBreakpoints.length) {
|
if (rowIndex < 0 || rowIndex >= allBreakpoints.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MspBreakpoint breakpoint = allBreakpoints[rowIndex];
|
Watchpoint breakpoint = allBreakpoints[rowIndex];
|
||||||
|
|
||||||
if (e.isPopupTrigger() || SwingUtilities.isRightMouseButton(e)) {
|
if (e.isPopupTrigger() || SwingUtilities.isRightMouseButton(e)) {
|
||||||
popupBreakpoint = breakpoint;
|
selectedWatchpoint = breakpoint;
|
||||||
popupMenu.show(table, e.getX(), e.getY());
|
popupMenu.show(table, e.getX(), e.getY());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realColumnIndex == COLUMN_INFO) {
|
if (realColumnIndex == COLUMN_INFO) {
|
||||||
String msg = JOptionPane.showInputDialog(
|
configureWatchpointInfo(breakpoint);
|
||||||
GUI.getTopParentContainer(),
|
|
||||||
"Enter description",
|
|
||||||
"Watchpoint Description",
|
|
||||||
JOptionPane.QUESTION_MESSAGE);
|
|
||||||
if (msg != null) {
|
|
||||||
breakpoint.setUserMessage(msg);
|
|
||||||
}
|
|
||||||
Color newColor = JColorChooser.showDialog(
|
|
||||||
GUI.getTopParentContainer(),
|
|
||||||
"Watchpoint Color",
|
|
||||||
breakpoint.getColor());
|
|
||||||
if (newColor != null) {
|
|
||||||
breakpoint.setColor(newColor);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = allBreakpoints[rowIndex].getCodeFile();
|
/*File file = allBreakpoints[rowIndex].getCodeFile();
|
||||||
int line = allBreakpoints[rowIndex].getLineNumber();
|
int line = allBreakpoints[rowIndex].getLineNumber();
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/* Display source code */
|
|
||||||
codeWatcher.displaySourceFile(file, line);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Update when breakpoints are triggered/added/removed */
|
|
||||||
breakpoints.addWatchpointListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
MspBreakpoint triggered = BreakpointsUI.this.breakpoints.getLastWatchpoint();
|
|
||||||
if (triggered == null) {
|
|
||||||
table.repaint();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
flashBreakpoint(triggered);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -232,24 +200,41 @@ public class BreakpointsUI extends JPanel {
|
|||||||
add(BorderLayout.CENTER, table);
|
add(BorderLayout.CENTER, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void flashBreakpoint(MspBreakpoint breakpoint) {
|
private void configureWatchpointInfo(Watchpoint breakpoint) {
|
||||||
/* Locate breakpoints table index */
|
String msg = (String) JOptionPane.showInputDialog(
|
||||||
int index = -1;
|
GUI.getTopParentContainer(),
|
||||||
MspBreakpoint[] all = breakpoints.getBreakpoints();
|
"Enter description;",
|
||||||
for (int i=0; i < breakpoints.getBreakpointsCount(); i++) {
|
"Watchpoint description",
|
||||||
if (breakpoint == all[i]) {
|
JOptionPane.QUESTION_MESSAGE, null, null, breakpoint.getUserMessage());
|
||||||
index = i;
|
if (msg == null) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (index < 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
breakpoint.setUserMessage(msg);
|
||||||
|
Color newColor = JColorChooser.showDialog(
|
||||||
|
GUI.getTopParentContainer(),
|
||||||
|
"Watchpoint color",
|
||||||
|
breakpoint.getColor());
|
||||||
|
if (newColor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
breakpoint.setColor(newColor);
|
||||||
|
}
|
||||||
|
|
||||||
final int breakpointIndex = index;
|
public void selectBreakpoint(final Watchpoint breakpoint) {
|
||||||
|
if (breakpoint == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Locate breakpoints table index */
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
table.setRowSelectionInterval(breakpointIndex, breakpointIndex);
|
Watchpoint[] watchpoints = mote.getBreakpoints();
|
||||||
|
for (int i=0; i < watchpoints.length; i++) {
|
||||||
|
if (breakpoint == watchpoints[i]) {
|
||||||
|
/* Select */
|
||||||
|
table.setRowSelectionInterval(i, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -259,18 +244,18 @@ public class BreakpointsUI extends JPanel {
|
|||||||
return COLUMN_NAMES[col].toString();
|
return COLUMN_NAMES[col].toString();
|
||||||
}
|
}
|
||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return breakpoints.getBreakpointsCount();
|
return mote.getBreakpoints().length;
|
||||||
}
|
}
|
||||||
public int getColumnCount() {
|
public int getColumnCount() {
|
||||||
return COLUMN_NAMES.length;
|
return COLUMN_NAMES.length;
|
||||||
}
|
}
|
||||||
public Object getValueAt(int row, int col) {
|
public Object getValueAt(int row, int col) {
|
||||||
MspBreakpoint breakpoint = breakpoints.getBreakpoints()[row];
|
Watchpoint breakpoint = mote.getBreakpoints()[row];
|
||||||
|
|
||||||
/* Executable address in hexadecimal */
|
/* Executable address in hexadecimal */
|
||||||
if (col == COLUMN_ADDRESS) {
|
if (col == COLUMN_ADDRESS) {
|
||||||
Integer address = breakpoint.getExecutableAddress();
|
Integer address = breakpoint.getExecutableAddress();
|
||||||
return "0x" + Integer.toHexString(address.intValue());
|
return String.format("0x%04x", address.intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Source file + line number */
|
/* Source file + line number */
|
||||||
@ -300,7 +285,7 @@ public class BreakpointsUI extends JPanel {
|
|||||||
return getColumnClass(col) == Boolean.class;
|
return getColumnClass(col) == Boolean.class;
|
||||||
}
|
}
|
||||||
public void setValueAt(Object value, int row, int col) {
|
public void setValueAt(Object value, int row, int col) {
|
||||||
MspBreakpoint breakpoint = breakpoints.getBreakpoints()[row];
|
Watchpoint breakpoint = mote.getBreakpoints()[row];
|
||||||
|
|
||||||
if (col == COLUMN_STOP) {
|
if (col == COLUMN_STOP) {
|
||||||
/* Toggle stop state */
|
/* Toggle stop state */
|
||||||
@ -308,109 +293,36 @@ public class BreakpointsUI extends JPanel {
|
|||||||
fireTableCellUpdated(row, col);
|
fireTableCellUpdated(row, col);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (col == COLUMN_REMOVE) {
|
|
||||||
/* Remove breakpoint */
|
|
||||||
Integer address = breakpoint.getExecutableAddress();
|
|
||||||
breakpoints.removeBreakpoint(address);
|
|
||||||
fireTableCellUpdated(row, col);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public Class<?> getColumnClass(int c) {
|
public Class<?> getColumnClass(int c) {
|
||||||
return getValueAt(0, c).getClass();
|
return getValueAt(0, c).getClass();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private Action addToMoteTypeAction = new AbstractAction("Register on all motes (mote type)") {
|
private Action gotoCodeAction = new AbstractAction("Show in source code") {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (popupBreakpoint == null) {
|
if (selectedWatchpoint == null) {
|
||||||
logger.fatal("No breakpoint to add");
|
return;
|
||||||
}
|
}
|
||||||
|
codeWatcher.displaySourceFile(selectedWatchpoint.getCodeFile(), selectedWatchpoint.getLineNumber(), false);
|
||||||
/* Extract all motes of the same mote type */
|
|
||||||
Simulation sim = popupBreakpoint.getMote().getSimulation();
|
|
||||||
MoteType type = popupBreakpoint.getMote().getType();
|
|
||||||
ArrayList<MspMote> motes = new ArrayList<MspMote>();
|
|
||||||
for (Mote m: sim.getMotes()) {
|
|
||||||
if (m.getType() == type) {
|
|
||||||
if (!(m instanceof MspMote)) {
|
|
||||||
logger.fatal("At least one mote was not a MSP mote: " + m);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
motes.add((MspMote)m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register breakpoints */
|
|
||||||
int reregistered = 0;
|
|
||||||
for (MspMote m: motes) {
|
|
||||||
/* Avoid duplicates (match executable addresses) */
|
|
||||||
MspBreakpointContainer container = m.getBreakpointsContainer();
|
|
||||||
MspBreakpoint[] breakpoints = container.getBreakpoints();
|
|
||||||
for (MspBreakpoint w: breakpoints) {
|
|
||||||
if (popupBreakpoint.getExecutableAddress().intValue() ==
|
|
||||||
w.getExecutableAddress().intValue()) {
|
|
||||||
logger.info("Reregistering breakpoint at mote: " + m);
|
|
||||||
container.removeBreakpoint(w.getExecutableAddress());
|
|
||||||
reregistered++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MspBreakpoint newBreakpoint = container.addBreakpoint(
|
|
||||||
popupBreakpoint.getCodeFile(),
|
|
||||||
popupBreakpoint.getLineNumber(),
|
|
||||||
popupBreakpoint.getExecutableAddress());
|
|
||||||
newBreakpoint.setUserMessage(popupBreakpoint.getUserMessage());
|
|
||||||
newBreakpoint.setColor(popupBreakpoint.getColor());
|
|
||||||
newBreakpoint.setStopsSimulation(popupBreakpoint.stopsSimulation());
|
|
||||||
}
|
|
||||||
|
|
||||||
JOptionPane.showMessageDialog(GUI.getTopParentContainer(),
|
|
||||||
"Registered " + motes.size() + " breakpoints (" + reregistered + " re-registered)",
|
|
||||||
"Breakpoints added", JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private Action delFromMoteTypeAction = new AbstractAction("Delete from all motes (mote type)") {
|
private Action removeWatchpointAction = new AbstractAction("Remove watchpoint") {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (popupBreakpoint == null) {
|
if (selectedWatchpoint == null) {
|
||||||
logger.fatal("No breakpoint to delete");
|
return;
|
||||||
}
|
}
|
||||||
|
mote.removeBreakpoint(selectedWatchpoint);
|
||||||
/* Extract all motes of the same mote type */
|
table.invalidate();
|
||||||
Simulation sim = popupBreakpoint.getMote().getSimulation();
|
table.repaint();
|
||||||
MoteType type = popupBreakpoint.getMote().getType();
|
}
|
||||||
ArrayList<MspMote> motes = new ArrayList<MspMote>();
|
};
|
||||||
for (Mote m: sim.getMotes()) {
|
private Action configureWatchpointAction = new AbstractAction("Configure watchpoint information") {
|
||||||
if (m.getType() == type) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (!(m instanceof MspMote)) {
|
if (selectedWatchpoint == null) {
|
||||||
logger.fatal("At least one mote was not a MSP mote: " + m);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
motes.add((MspMote)m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
configureWatchpointInfo(selectedWatchpoint);
|
||||||
/* Delete breakpoints */
|
|
||||||
int deleted = 0;
|
|
||||||
for (MspMote m: motes) {
|
|
||||||
/* Avoid duplicates (match executable addresses) */
|
|
||||||
MspBreakpointContainer container = m.getBreakpointsContainer();
|
|
||||||
MspBreakpoint[] breakpoints = container.getBreakpoints();
|
|
||||||
for (MspBreakpoint w: breakpoints) {
|
|
||||||
if (popupBreakpoint.getExecutableAddress().intValue() ==
|
|
||||||
w.getExecutableAddress().intValue()) {
|
|
||||||
container.removeBreakpoint(w.getExecutableAddress());
|
|
||||||
deleted++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JOptionPane.showMessageDialog(GUI.getTopParentContainer(),
|
|
||||||
"Deleted " + deleted + " breakpoints",
|
|
||||||
"Breakpoints deleted", JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -34,32 +34,33 @@ package se.sics.cooja.mspmote.plugins;
|
|||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Font;
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.awt.event.MouseAdapter;
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.HashMap;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import javax.swing.AbstractListModel;
|
import javax.swing.JEditorPane;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JList;
|
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.JSeparator;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.ListCellRenderer;
|
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.event.PopupMenuEvent;
|
||||||
|
import javax.swing.event.PopupMenuListener;
|
||||||
|
import javax.swing.text.BadLocationException;
|
||||||
|
import javax.swing.text.Highlighter;
|
||||||
|
import javax.swing.text.Highlighter.HighlightPainter;
|
||||||
|
|
||||||
|
import jsyntaxpane.DefaultSyntaxKit;
|
||||||
|
import jsyntaxpane.components.Markers.SimpleMarker;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import se.sics.mspsim.extutil.highlight.CScanner;
|
import se.sics.cooja.Watchpoint;
|
||||||
import se.sics.mspsim.extutil.highlight.Token;
|
import se.sics.cooja.WatchpointMote;
|
||||||
import se.sics.mspsim.extutil.highlight.TokenTypes;
|
import se.sics.cooja.util.JSyntaxAddBreakpoint;
|
||||||
|
import se.sics.cooja.util.JSyntaxRemoveBreakpoint;
|
||||||
|
import se.sics.cooja.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays source code and allows a user to add and remove breakpoints.
|
* Displays source code and allows a user to add and remove breakpoints.
|
||||||
@ -69,184 +70,231 @@ import se.sics.mspsim.extutil.highlight.TokenTypes;
|
|||||||
public class CodeUI extends JPanel {
|
public class CodeUI extends JPanel {
|
||||||
private static Logger logger = Logger.getLogger(CodeUI.class);
|
private static Logger logger = Logger.getLogger(CodeUI.class);
|
||||||
|
|
||||||
private JPanel panel = null;
|
{
|
||||||
private JList codeList = null;
|
DefaultSyntaxKit.initKit();
|
||||||
|
}
|
||||||
|
|
||||||
private MspBreakpointContainer breakpoints = null;
|
private JEditorPane codeEditor = null;
|
||||||
|
private HashMap<Integer, Integer> codeEditorLines = null;
|
||||||
protected File displayedFile = null;
|
protected File displayedFile = null;
|
||||||
|
|
||||||
private Token tokensArray[][] = null;
|
private static final HighlightPainter CURRENT_LINE_MARKER = new SimpleMarker(Color.ORANGE);
|
||||||
private int tokensStartPos[] = null;
|
private static final HighlightPainter SELECTED_LINE_MARKER = new SimpleMarker(Color.GREEN);
|
||||||
|
private static final HighlightPainter BREAKPOINTS_MARKER = new SimpleMarker(Color.LIGHT_GRAY);
|
||||||
|
private final Object currentLineTag;
|
||||||
|
private final Object selectedLineTag;
|
||||||
|
private final ArrayList<Object> breakpointsLineTags = new ArrayList<Object>();
|
||||||
|
|
||||||
/**
|
private JSyntaxAddBreakpoint actionAddBreakpoint = null;
|
||||||
* @param breakpoints Breakpoints
|
private JSyntaxRemoveBreakpoint actionRemoveBreakpoint = null;
|
||||||
*/
|
|
||||||
public CodeUI(MspBreakpointContainer breakpoints) {
|
private WatchpointMote mote;
|
||||||
this.breakpoints = breakpoints;
|
|
||||||
|
public CodeUI(WatchpointMote mote) {
|
||||||
|
this.mote = mote;
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Workaround to configure jsyntaxpane */
|
||||||
|
JEditorPane e = new JEditorPane();
|
||||||
|
new JScrollPane(e);
|
||||||
|
e.setContentType("text/c");
|
||||||
|
DefaultSyntaxKit kit = (DefaultSyntaxKit) e.getEditorKit();
|
||||||
|
kit.setProperty("Action.addbreakpoint", JSyntaxAddBreakpoint.class.getName());
|
||||||
|
kit.setProperty("Action.removebreakpoint", JSyntaxRemoveBreakpoint.class.getName());
|
||||||
|
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,addbreakpoint,removebreakpoint");
|
||||||
|
}
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
|
codeEditor = new JEditorPane();
|
||||||
|
add(new JScrollPane(codeEditor), BorderLayout.CENTER);
|
||||||
|
doLayout();
|
||||||
|
|
||||||
panel = new JPanel(new BorderLayout());
|
codeEditorLines = new HashMap<Integer, Integer>();
|
||||||
add(panel, BorderLayout.CENTER);
|
codeEditor.setContentType("text/c");
|
||||||
displayNoCode();
|
DefaultSyntaxKit kit = (DefaultSyntaxKit) codeEditor.getEditorKit();
|
||||||
|
kit.setProperty("Action.addbreakpoint", JSyntaxAddBreakpoint.class.getName());
|
||||||
|
kit.setProperty("Action.removebreakpoint", JSyntaxRemoveBreakpoint.class.getName());
|
||||||
|
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,addbreakpoint,removebreakpoint");
|
||||||
|
|
||||||
breakpoints.addWatchpointListener(new ActionListener() {
|
JPopupMenu p = codeEditor.getComponentPopupMenu();
|
||||||
public void actionPerformed(ActionEvent e) {
|
for (Component c: p.getComponents()) {
|
||||||
/* Only update code list if simulation is not running */
|
if (c instanceof JMenuItem) {
|
||||||
if (CodeUI.this.breakpoints.getMote().getSimulation().isRunning() ||
|
if (((JMenuItem) c).getAction() != null &&
|
||||||
CodeUI.this.breakpoints.getLastWatchpoint() != null) {
|
((JMenuItem) c).getAction() instanceof JSyntaxAddBreakpoint) {
|
||||||
|
actionAddBreakpoint = (JSyntaxAddBreakpoint)(((JMenuItem) c).getAction());
|
||||||
|
actionAddBreakpoint.setMenuText("Add breakpoint");
|
||||||
|
}
|
||||||
|
if (((JMenuItem) c).getAction() != null &&
|
||||||
|
((JMenuItem) c).getAction() instanceof JSyntaxRemoveBreakpoint) {
|
||||||
|
actionRemoveBreakpoint = (JSyntaxRemoveBreakpoint)(((JMenuItem) c).getAction());
|
||||||
|
actionRemoveBreakpoint.setMenuText("Remove breakpoint");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
codeEditor.setText("");
|
||||||
|
codeEditorLines.clear();
|
||||||
|
codeEditor.setEditable(false);
|
||||||
|
|
||||||
|
Highlighter hl = codeEditor.getHighlighter();
|
||||||
|
Object o = null;
|
||||||
|
try {
|
||||||
|
o = hl.addHighlight(0, 0, CURRENT_LINE_MARKER);
|
||||||
|
} catch (BadLocationException e1) {
|
||||||
|
}
|
||||||
|
currentLineTag = o;
|
||||||
|
|
||||||
|
o = null;
|
||||||
|
try {
|
||||||
|
o = hl.addHighlight(0, 0, SELECTED_LINE_MARKER);
|
||||||
|
} catch (BadLocationException e1) {
|
||||||
|
}
|
||||||
|
selectedLineTag = o;
|
||||||
|
|
||||||
|
codeEditor.getComponentPopupMenu().addPopupMenuListener(new PopupMenuListener() {
|
||||||
|
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
|
||||||
|
/* Disable breakpoint actions */
|
||||||
|
actionAddBreakpoint.setEnabled(false);
|
||||||
|
actionRemoveBreakpoint.setEnabled(false);
|
||||||
|
|
||||||
|
int line = getCodeEditorMouseLine();
|
||||||
|
if (line < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
/* Configure breakpoint menu options */
|
||||||
public void run() {
|
Integer address =
|
||||||
if (codeList != null) {
|
CodeUI.this.mote.getExecutableAddressOf(displayedFile, line);
|
||||||
codeList.updateUI();
|
if (address == null) {
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
});
|
final int start = codeEditorLines.get(line);
|
||||||
|
int end = codeEditorLines.get(line+1);
|
||||||
|
Highlighter hl = codeEditor.getHighlighter();
|
||||||
|
try {
|
||||||
|
hl.changeHighlight(selectedLineTag, start, end);
|
||||||
|
} catch (BadLocationException e1) {
|
||||||
|
}
|
||||||
|
boolean hasBreakpoint =
|
||||||
|
CodeUI.this.mote.breakpointExists(address);
|
||||||
|
if (!hasBreakpoint) {
|
||||||
|
actionAddBreakpoint.setEnabled(true);
|
||||||
|
actionAddBreakpoint.putValue("WatchpointMote", CodeUI.this.mote);
|
||||||
|
actionAddBreakpoint.putValue("WatchpointFile", displayedFile);
|
||||||
|
actionAddBreakpoint.putValue("WatchpointLine", new Integer(line));
|
||||||
|
actionAddBreakpoint.putValue("WatchpointAddress", new Integer(address));
|
||||||
|
} else {
|
||||||
|
actionRemoveBreakpoint.setEnabled(true);
|
||||||
|
actionRemoveBreakpoint.putValue("WatchpointMote", CodeUI.this.mote);
|
||||||
|
actionRemoveBreakpoint.putValue("WatchpointFile", displayedFile);
|
||||||
|
actionRemoveBreakpoint.putValue("WatchpointLine", new Integer(line));
|
||||||
|
actionRemoveBreakpoint.putValue("WatchpointAddress", new Integer(address));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
||||||
|
Highlighter hl = codeEditor.getHighlighter();
|
||||||
|
try {
|
||||||
|
hl.changeHighlight(selectedLineTag, 0, 0);
|
||||||
|
} catch (BadLocationException e1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
displayNoCode(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBreakpoints() {
|
||||||
|
Highlighter hl = codeEditor.getHighlighter();
|
||||||
|
|
||||||
|
for (Object breakpointsLineTag: breakpointsLineTags) {
|
||||||
|
hl.removeHighlight(breakpointsLineTag);
|
||||||
|
}
|
||||||
|
breakpointsLineTags.clear();
|
||||||
|
|
||||||
|
for (Watchpoint w: mote.getBreakpoints()) {
|
||||||
|
if (!w.getCodeFile().equals(displayedFile)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int start = codeEditorLines.get(w.getLineNumber());
|
||||||
|
int end = codeEditorLines.get(w.getLineNumber()+1);
|
||||||
|
try {
|
||||||
|
breakpointsLineTags.add(hl.addHighlight(start, end, BREAKPOINTS_MARKER));
|
||||||
|
} catch (BadLocationException e1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getCodeEditorMouseLine() {
|
||||||
|
if (codeEditorLines == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Point mousePos = codeEditor.getMousePosition();
|
||||||
|
if (mousePos == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int modelPos = codeEditor.viewToModel(mousePos);
|
||||||
|
int line = 1;
|
||||||
|
while (codeEditorLines.containsKey(line+1)) {
|
||||||
|
int next = codeEditorLines.get(line+1);
|
||||||
|
if (modelPos < next) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove any shown source code.
|
* Remove any shown source code.
|
||||||
*/
|
*/
|
||||||
public void displayNoCode() {
|
public void displayNoCode(final boolean markCurrent) {
|
||||||
// Display "no code" message
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
panel.removeAll();
|
displayedFile = null;
|
||||||
panel.repaint();
|
codeEditor.setText(null);
|
||||||
|
codeEditorLines.clear();
|
||||||
|
displayLine(-1, markCurrent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
displayedFile = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createTokens(String[] codeData) {
|
|
||||||
|
|
||||||
/* Merge code lines */
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (String line: codeData) {
|
|
||||||
sb.append(line);
|
|
||||||
sb.append('\n');
|
|
||||||
}
|
|
||||||
String code = sb.toString();
|
|
||||||
|
|
||||||
/* Scan code */
|
|
||||||
CScanner cScanner = new CScanner();
|
|
||||||
cScanner.change(0, 0, code.length());
|
|
||||||
int nrTokens;
|
|
||||||
nrTokens = cScanner.scan(code.toCharArray(), 0, code.length());
|
|
||||||
|
|
||||||
/* Extract tokens */
|
|
||||||
ArrayList<Token> codeTokensVector = new ArrayList<Token>();
|
|
||||||
for (int i=0; i < nrTokens; i++) {
|
|
||||||
Token token = cScanner.getToken(i);
|
|
||||||
codeTokensVector.add(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create new line token array */
|
|
||||||
Token newTokensArray[][] = new Token[codeData.length][];
|
|
||||||
int[] newTokensStartPos = new int[codeData.length];
|
|
||||||
int lineStart=0, lineEnd=-1;
|
|
||||||
Iterator<Token> tokens = codeTokensVector.iterator();
|
|
||||||
Token currentToken = tokens.next();
|
|
||||||
for (int i=0; i < newTokensArray.length; i++) {
|
|
||||||
lineStart = lineEnd + 1;
|
|
||||||
lineEnd = lineStart + codeData[i].length();
|
|
||||||
|
|
||||||
newTokensStartPos[i] = lineStart;;
|
|
||||||
|
|
||||||
/* Advance tokens until correct line */
|
|
||||||
while (currentToken.position + currentToken.symbol.name.length() < lineStart) {
|
|
||||||
if (!tokens.hasNext()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
currentToken = tokens.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Advance tokens until last token on line */
|
|
||||||
Vector<Token> lineTokens = new Vector<Token>();
|
|
||||||
while (currentToken.position < lineEnd) {
|
|
||||||
lineTokens.add(currentToken);
|
|
||||||
|
|
||||||
if (!tokens.hasNext()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
currentToken = tokens.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentToken == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store line tokens */
|
|
||||||
Token[] lineTokensArray = new Token[lineTokens.size()];
|
|
||||||
for (int j=0; j < lineTokens.size(); j++) {
|
|
||||||
lineTokensArray[j] = lineTokens.get(j);
|
|
||||||
}
|
|
||||||
newTokensArray[i] = lineTokensArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start using tokens array */
|
|
||||||
tokensArray = newTokensArray;
|
|
||||||
tokensStartPos = newTokensStartPos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display given source code and mark given line.
|
* Display given source code and mark given line.
|
||||||
*
|
*
|
||||||
* @param codeFile Source code file
|
* @param codeFile Source code file
|
||||||
* @param codeData Source code
|
|
||||||
* @param lineNr Line numer
|
* @param lineNr Line numer
|
||||||
*/
|
*/
|
||||||
public void displayNewCode(File codeFile, String[] codeData, final int lineNr) {
|
public void displayNewCode(final File codeFile, final int lineNr, final boolean markCurrent) {
|
||||||
displayedFile = codeFile;
|
if (!codeFile.equals(displayedFile)) {
|
||||||
|
/* Read from disk */
|
||||||
|
final String data = StringUtils.loadFromFile(codeFile);
|
||||||
|
if (data == null || data.length() == 0) {
|
||||||
|
displayNoCode(markCurrent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (codeData == null || codeData.length == 0) {
|
String[] lines = data.split("\n");
|
||||||
displayNoCode();
|
logger.info("Opening " + codeFile + " (" + lines.length + " lines)");
|
||||||
return;
|
int length = 0;
|
||||||
|
codeEditorLines.clear();
|
||||||
|
for (int line=1; line-1 < lines.length; line++) {
|
||||||
|
codeEditorLines.put(line, length);
|
||||||
|
length += lines[line-1].length()+1;
|
||||||
|
}
|
||||||
|
codeEditor.setText(data.toString());
|
||||||
|
displayedFile = codeFile;
|
||||||
|
updateBreakpoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Opening " + codeFile + " (" + codeData.length + " lines)");
|
|
||||||
|
|
||||||
/* Create new list */
|
|
||||||
final JList newList = new JList(new CodeListModel(codeData));
|
|
||||||
newList.setBackground(Color.WHITE);
|
|
||||||
newList.setFont(new Font("courier", 0, 12));
|
|
||||||
newList.setCellRenderer(new CodeCellRenderer(lineNr));
|
|
||||||
((CodeCellRenderer)newList.getCellRenderer()).setNice(false);
|
|
||||||
newList.setFixedCellHeight(12);
|
|
||||||
newList.addMouseListener(new MouseAdapter() {
|
|
||||||
public void mousePressed(MouseEvent e) {
|
|
||||||
handleMouseEvent(e);
|
|
||||||
}
|
|
||||||
public void mouseReleased(MouseEvent e) {
|
|
||||||
handleMouseEvent(e);
|
|
||||||
}
|
|
||||||
public void mouseEntered(MouseEvent e) {
|
|
||||||
handleMouseEvent(e);
|
|
||||||
}
|
|
||||||
public void mouseExited(MouseEvent e) {
|
|
||||||
handleMouseEvent(e);
|
|
||||||
}
|
|
||||||
public void mouseClicked(MouseEvent e) {
|
|
||||||
handleMouseEvent(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
createTokens(codeData);
|
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
panel.removeAll();
|
displayLine(lineNr, markCurrent);
|
||||||
codeList = newList;
|
|
||||||
panel.add(codeList);
|
|
||||||
panel.validate();
|
|
||||||
displayLine(lineNr);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,290 +303,35 @@ public class CodeUI extends JPanel {
|
|||||||
*
|
*
|
||||||
* @param lineNumber Line number
|
* @param lineNumber Line number
|
||||||
*/
|
*/
|
||||||
public void displayLine(int lineNumber) {
|
private void displayLine(int lineNumber, boolean markCurrent) {
|
||||||
if (codeList == null) {
|
try {
|
||||||
return;
|
if (markCurrent) {
|
||||||
}
|
/* remove previous highlight */
|
||||||
|
Highlighter hl = codeEditor.getHighlighter();
|
||||||
((CodeCellRenderer) codeList.getCellRenderer()).setNice(false);
|
hl.changeHighlight(currentLineTag, 0, 0);
|
||||||
((CodeCellRenderer) codeList.getCellRenderer()).changeCurrentLine(lineNumber);
|
|
||||||
((CodeCellRenderer) codeList.getCellRenderer()).validate();
|
|
||||||
|
|
||||||
if (lineNumber > 0) {
|
|
||||||
int index = lineNumber - 1;
|
|
||||||
codeList.setSelectedIndex(index);
|
|
||||||
codeList.ensureIndexIsVisible(Math.max(0, index-3));
|
|
||||||
codeList.ensureIndexIsVisible(Math.min(index+3, codeList.getModel().getSize()));
|
|
||||||
codeList.ensureIndexIsVisible(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
codeList.updateUI();
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
((CodeCellRenderer) codeList.getCellRenderer()).setNice(true);
|
|
||||||
codeList.repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleMouseEvent(MouseEvent event) {
|
|
||||||
if (event.isPopupTrigger()) {
|
|
||||||
Point menuLocation = codeList.getPopupLocation(event);
|
|
||||||
if (menuLocation == null) {
|
|
||||||
menuLocation = new Point(
|
|
||||||
codeList.getLocationOnScreen().x + event.getX(),
|
|
||||||
codeList.getLocationOnScreen().y + event.getY());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final int currentLine = codeList.locationToIndex(new Point(event.getX(), event.getY())) + 1;
|
if (lineNumber >= 0) {
|
||||||
codeList.setSelectedIndex(currentLine - 1);
|
final int start = codeEditorLines.get(lineNumber);
|
||||||
JPopupMenu popupMenu = createPopupMenu(displayedFile, currentLine);
|
int end = codeEditorLines.get(lineNumber+1);
|
||||||
|
if (markCurrent) {
|
||||||
popupMenu.setLocation(menuLocation);
|
/* highlight code */
|
||||||
popupMenu.setInvoker(codeList);
|
Highlighter hl = codeEditor.getHighlighter();
|
||||||
popupMenu.setVisible(true);
|
hl.changeHighlight(currentLineTag, start, end);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private JPopupMenu createPopupMenu(final File codeFile, final int lineNr) {
|
|
||||||
final Integer executableAddress = breakpoints.getExecutableAddressOf(codeFile, lineNr);
|
|
||||||
boolean breakpointExists = breakpoints.breakpointExists(codeFile, lineNr);
|
|
||||||
|
|
||||||
JPopupMenu menuMotePlugins = new JPopupMenu();
|
|
||||||
JMenuItem headerMenuItem = new JMenuItem("Breakpoints:");
|
|
||||||
headerMenuItem.setEnabled(false);
|
|
||||||
menuMotePlugins.add(headerMenuItem);
|
|
||||||
menuMotePlugins.add(new JSeparator());
|
|
||||||
|
|
||||||
JMenuItem addBreakpointMenuItem = new JMenuItem("Add breakpoint on line " + lineNr);
|
|
||||||
if (executableAddress == null || breakpointExists) {
|
|
||||||
addBreakpointMenuItem.setEnabled(false);
|
|
||||||
} else {
|
|
||||||
addBreakpointMenuItem.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
breakpoints.addBreakpoint(codeFile, lineNr, executableAddress);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
menuMotePlugins.add(addBreakpointMenuItem);
|
|
||||||
|
|
||||||
JMenuItem delBreakpointMenuItem = new JMenuItem("Delete breakpoint on line " + lineNr);
|
/* ensure visible */
|
||||||
if (executableAddress == null || !breakpointExists) {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
delBreakpointMenuItem.setEnabled(false);
|
public void run() {
|
||||||
} else {
|
try {
|
||||||
delBreakpointMenuItem.addActionListener(new ActionListener() {
|
codeEditor.scrollRectToVisible(codeEditor.modelToView(start));
|
||||||
public void actionPerformed(ActionEvent e) {
|
} catch (BadLocationException e) {
|
||||||
breakpoints.removeBreakpoint(executableAddress);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
menuMotePlugins.add(delBreakpointMenuItem);
|
|
||||||
|
|
||||||
return menuMotePlugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CodeListModel extends AbstractListModel {
|
|
||||||
private String[] codeData;
|
|
||||||
|
|
||||||
public CodeListModel(String[] codeData) {
|
|
||||||
super();
|
|
||||||
this.codeData = codeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSize() {
|
|
||||||
if (codeData == null || codeData.length == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return codeData.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getElementAt(int index) {
|
|
||||||
if (codeData == null || codeData.length == 0) {
|
|
||||||
return "No code to display";
|
|
||||||
}
|
|
||||||
|
|
||||||
return codeData[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FROM: http://www.rgagnon.com/javadetails/java-0306.html, 03/19/2008 */
|
|
||||||
private static String stringToHTMLString(String string) {
|
|
||||||
StringBuffer sb = new StringBuffer(string.length());
|
|
||||||
boolean lastWasBlankChar = false;
|
|
||||||
int len = string.length();
|
|
||||||
char c;
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
c = string.charAt(i);
|
|
||||||
if (c == ' ') {
|
|
||||||
if (lastWasBlankChar) {
|
|
||||||
lastWasBlankChar = false;
|
|
||||||
sb.append(" ");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lastWasBlankChar = true;
|
|
||||||
sb.append(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lastWasBlankChar = false;
|
|
||||||
//
|
|
||||||
// HTML Special Chars
|
|
||||||
if (c == '"') {
|
|
||||||
sb.append(""");
|
|
||||||
} else if (c == '&') {
|
|
||||||
sb.append("&");
|
|
||||||
} else if (c == '<') {
|
|
||||||
sb.append("<");
|
|
||||||
} else if (c == '>') {
|
|
||||||
sb.append(">");
|
|
||||||
} else if (c == '\n') {
|
|
||||||
// Handle Newline
|
|
||||||
sb.append("<br/>");
|
|
||||||
} else {
|
|
||||||
int ci = 0xffff & c;
|
|
||||||
if (ci < 160 ) {
|
|
||||||
// nothing special only 7 Bit
|
|
||||||
sb.append(c);
|
|
||||||
} else {
|
|
||||||
// Not 7 Bit use the unicode system
|
|
||||||
sb.append("&#");
|
|
||||||
sb.append(new Integer(ci).toString());
|
|
||||||
sb.append(';');
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("Error when highlighting current line: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CodeCellRenderer extends JLabel implements ListCellRenderer {
|
|
||||||
private int currentIndex;
|
|
||||||
private boolean nice = true;
|
|
||||||
|
|
||||||
public CodeCellRenderer(int currentLineNr) {
|
|
||||||
this.currentIndex = currentLineNr - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNice(boolean b) {
|
|
||||||
nice = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void changeCurrentLine(int currentLineNr) {
|
|
||||||
this.currentIndex = currentLineNr - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getColoredLabelText(int lineNr, int lineStartPos, Token[] tokens, String code) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("<html>");
|
|
||||||
|
|
||||||
/* Add line number */
|
|
||||||
String lineString = "0000" + Integer.toString(lineNr);
|
|
||||||
lineString = lineString.substring(lineString.length() - 4);
|
|
||||||
sb.append("<font color=\"333333\">");
|
|
||||||
sb.append(lineString);
|
|
||||||
sb.append(": </font>");
|
|
||||||
|
|
||||||
/* Add code */
|
|
||||||
if (tokens == null || tokens.length == 0 || lineStartPos < 0) {
|
|
||||||
sb.append("<font color=\"000000\">");
|
|
||||||
sb.append(code);
|
|
||||||
sb.append("</font>");
|
|
||||||
} else {
|
|
||||||
for (int i=tokens.length-1; i >= 0; i--) {
|
|
||||||
Token subToken = tokens[i];
|
|
||||||
|
|
||||||
String colorString = "000000";
|
|
||||||
|
|
||||||
/* Determine code color */
|
|
||||||
final int type = subToken.symbol.type;
|
|
||||||
switch (type) {
|
|
||||||
case TokenTypes.COMMENT:
|
|
||||||
case TokenTypes.START_COMMENT:
|
|
||||||
case TokenTypes.MID_COMMENT:
|
|
||||||
case TokenTypes.END_COMMENT:
|
|
||||||
colorString = "00AA00";
|
|
||||||
break;
|
|
||||||
case TokenTypes.STRING:
|
|
||||||
colorString = "0000AA";
|
|
||||||
break;
|
|
||||||
case TokenTypes.KEYWORD:
|
|
||||||
case TokenTypes.KEYWORD2:
|
|
||||||
colorString = "AA0000";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract part of token residing in current line */
|
|
||||||
int tokenLinePos;
|
|
||||||
String subCode;
|
|
||||||
if (subToken.position < lineStartPos) {
|
|
||||||
subCode = subToken.symbol.name.substring(lineStartPos - subToken.position);
|
|
||||||
tokenLinePos = 0;
|
|
||||||
} else if (subToken.position + subToken.symbol.name.length() > lineStartPos + code.length()) {
|
|
||||||
subCode = subToken.symbol.name.substring(0, code.length() + lineStartPos - subToken.position);
|
|
||||||
tokenLinePos = subToken.position - lineStartPos;
|
|
||||||
} else {
|
|
||||||
subCode = subToken.symbol.name;
|
|
||||||
tokenLinePos = subToken.position - lineStartPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
subCode = stringToHTMLString(subCode);
|
|
||||||
String firstPart = code.substring(0, tokenLinePos);
|
|
||||||
String coloredSubCode = "<font color=\"" + colorString + "\">" + subCode + "</font>";
|
|
||||||
String lastPart =
|
|
||||||
tokenLinePos + subToken.symbol.name.length() >= code.length()?
|
|
||||||
"":code.substring(tokenLinePos + subToken.symbol.name.length());
|
|
||||||
|
|
||||||
code = firstPart + coloredSubCode + lastPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
code = code.replace(" ", " ");
|
|
||||||
sb.append(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.append("</html>");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getListCellRendererComponent(
|
|
||||||
JList list,
|
|
||||||
Object value,
|
|
||||||
int index,
|
|
||||||
boolean isSelected,
|
|
||||||
boolean cellHasFocus)
|
|
||||||
{
|
|
||||||
int lineNr = index + 1;
|
|
||||||
if (!nice) {
|
|
||||||
setText((String) value);
|
|
||||||
} else if (tokensArray != null && index < tokensArray.length && tokensArray[index] != null) {
|
|
||||||
setText(getColoredLabelText(lineNr, tokensStartPos[index], tokensArray[index], (String) value));
|
|
||||||
} else {
|
|
||||||
setText(getColoredLabelText(lineNr, 0, null, (String) value));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == currentIndex) {
|
|
||||||
setBackground(Color.green);
|
|
||||||
} else if (isSelected) {
|
|
||||||
setBackground(list.getSelectionBackground());
|
|
||||||
setForeground(list.getSelectionForeground());
|
|
||||||
} else {
|
|
||||||
setBackground(list.getBackground());
|
|
||||||
setForeground(list.getForeground());
|
|
||||||
}
|
|
||||||
setEnabled(list.isEnabled());
|
|
||||||
|
|
||||||
if (breakpoints.breakpointExists(displayedFile, lineNr)) {
|
|
||||||
setFont(list.getFont().deriveFont(Font.BOLD));
|
|
||||||
} else {
|
|
||||||
setFont(list.getFont());
|
|
||||||
}
|
|
||||||
|
|
||||||
setOpaque(true);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,18 +30,16 @@
|
|||||||
package se.sics.cooja.mspmote.plugins;
|
package se.sics.cooja.mspmote.plugins;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
@ -54,8 +52,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JTabbedPane;
|
||||||
import javax.swing.JSplitPane;
|
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.filechooser.FileFilter;
|
import javax.swing.filechooser.FileFilter;
|
||||||
@ -72,11 +69,12 @@ import se.sics.cooja.MotePlugin;
|
|||||||
import se.sics.cooja.PluginType;
|
import se.sics.cooja.PluginType;
|
||||||
import se.sics.cooja.Simulation;
|
import se.sics.cooja.Simulation;
|
||||||
import se.sics.cooja.VisPlugin;
|
import se.sics.cooja.VisPlugin;
|
||||||
|
import se.sics.cooja.Watchpoint;
|
||||||
|
import se.sics.cooja.WatchpointMote;
|
||||||
|
import se.sics.cooja.WatchpointMote.WatchpointListener;
|
||||||
import se.sics.cooja.mspmote.MspMote;
|
import se.sics.cooja.mspmote.MspMote;
|
||||||
import se.sics.cooja.mspmote.MspMoteType;
|
import se.sics.cooja.mspmote.MspMoteType;
|
||||||
import se.sics.cooja.util.StringUtils;
|
|
||||||
import se.sics.mspsim.core.EmulationException;
|
import se.sics.mspsim.core.EmulationException;
|
||||||
import se.sics.mspsim.core.MSP430;
|
|
||||||
import se.sics.mspsim.ui.DebugUI;
|
import se.sics.mspsim.ui.DebugUI;
|
||||||
import se.sics.mspsim.util.DebugInfo;
|
import se.sics.mspsim.util.DebugInfo;
|
||||||
import se.sics.mspsim.util.ELFDebug;
|
import se.sics.mspsim.util.ELFDebug;
|
||||||
@ -85,25 +83,31 @@ import se.sics.mspsim.util.ELFDebug;
|
|||||||
@PluginType(PluginType.MOTE_PLUGIN)
|
@PluginType(PluginType.MOTE_PLUGIN)
|
||||||
public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
||||||
private static final long serialVersionUID = -8463196456352243367L;
|
private static final long serialVersionUID = -8463196456352243367L;
|
||||||
|
|
||||||
|
private static final int SOURCECODE = 0;
|
||||||
|
private static final int BREAKPOINTS = 2;
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(MspCodeWatcher.class);
|
private static Logger logger = Logger.getLogger(MspCodeWatcher.class);
|
||||||
private Simulation simulation;
|
private Simulation simulation;
|
||||||
private Observer simObserver;
|
private Observer simObserver;
|
||||||
private MspMote mspMote;
|
|
||||||
|
|
||||||
private File currentCodeFile = null;
|
private File currentCodeFile = null;
|
||||||
private int currentLineNumber = -1;
|
private int currentLineNumber = -1;
|
||||||
|
|
||||||
private JSplitPane leftSplitPane, rightSplitPane;
|
|
||||||
private DebugUI assCodeUI;
|
private DebugUI assCodeUI;
|
||||||
private CodeUI sourceCodeUI;
|
private CodeUI sourceCodeUI;
|
||||||
private BreakpointsUI breakpointsUI;
|
private BreakpointsUI breakpointsUI;
|
||||||
|
|
||||||
private MspBreakpointContainer breakpoints = null;
|
private MspMote mspMote; /* currently the only supported mote */
|
||||||
|
private WatchpointMote watchpointMote;
|
||||||
|
private WatchpointListener watchpointListener;
|
||||||
|
|
||||||
private JComboBox fileComboBox;
|
private JComboBox fileComboBox;
|
||||||
private String[] debugInfoMap = null;
|
private String[] debugInfoMap = null;
|
||||||
private File[] sourceFiles;
|
private File[] sourceFiles;
|
||||||
|
|
||||||
|
private JTabbedPane mainPane;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mini-debugger for MSP Motes.
|
* Mini-debugger for MSP Motes.
|
||||||
* Visualizes instructions, source code and allows a user to manipulate breakpoints.
|
* Visualizes instructions, source code and allows a user to manipulate breakpoints.
|
||||||
@ -113,15 +117,13 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
* @param gui Simulator
|
* @param gui Simulator
|
||||||
*/
|
*/
|
||||||
public MspCodeWatcher(Mote mote, Simulation simulationToVisualize, GUI gui) {
|
public MspCodeWatcher(Mote mote, Simulation simulationToVisualize, GUI gui) {
|
||||||
super("Msp Code Watcher", gui);
|
super("Msp Code Watcher - " + mote, gui);
|
||||||
this.mspMote = (MspMote) mote;
|
|
||||||
simulation = simulationToVisualize;
|
simulation = simulationToVisualize;
|
||||||
|
this.mspMote = (MspMote) mote;
|
||||||
|
this.watchpointMote = (WatchpointMote) mote;
|
||||||
|
|
||||||
getContentPane().setLayout(new BorderLayout());
|
getContentPane().setLayout(new BorderLayout());
|
||||||
|
|
||||||
/* Breakpoints */
|
|
||||||
breakpoints = mspMote.getBreakpointsContainer();
|
|
||||||
|
|
||||||
/* Create source file list */
|
/* Create source file list */
|
||||||
fileComboBox = new JComboBox();
|
fileComboBox = new JComboBox();
|
||||||
fileComboBox.addActionListener(new ActionListener() {
|
fileComboBox.addActionListener(new ActionListener() {
|
||||||
@ -149,58 +151,68 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
updateFileComboBox();
|
updateFileComboBox();
|
||||||
|
|
||||||
/* Browse code control (north) */
|
/* Browse code control (north) */
|
||||||
JButton currentFileButton = new JButton(currentFileAction);
|
Box sourceCodeControl = Box.createHorizontalBox();
|
||||||
JButton mapButton = new JButton(mapAction);
|
sourceCodeControl.add(new JButton(stepAction));
|
||||||
|
sourceCodeControl.add(Box.createHorizontalStrut(10));
|
||||||
Box browseBox = Box.createHorizontalBox();
|
sourceCodeControl.add(new JLabel("Current location: "));
|
||||||
browseBox.add(Box.createHorizontalStrut(10));
|
sourceCodeControl.add(new JButton(currentFileAction));
|
||||||
browseBox.add(new JLabel("Program counter: "));
|
sourceCodeControl.add(Box.createHorizontalGlue());
|
||||||
browseBox.add(currentFileButton);
|
sourceCodeControl.add(new JLabel("Source files: "));
|
||||||
browseBox.add(Box.createHorizontalGlue());
|
sourceCodeControl.add(fileComboBox);
|
||||||
browseBox.add(new JLabel("Browse: "));
|
sourceCodeControl.add(Box.createHorizontalStrut(5));
|
||||||
browseBox.add(fileComboBox);
|
sourceCodeControl.add(new JButton(mapAction));
|
||||||
browseBox.add(Box.createHorizontalStrut(10));
|
sourceCodeControl.add(Box.createHorizontalStrut(10));
|
||||||
browseBox.add(mapButton);
|
|
||||||
browseBox.add(Box.createHorizontalStrut(10));
|
|
||||||
|
|
||||||
/* Execution control panel (south) */
|
/* Execution control panel (south of source code panel) */
|
||||||
JPanel controlPanel = new JPanel();
|
|
||||||
JButton button = new JButton(stepAction);
|
/* Layout */
|
||||||
controlPanel.add(button);
|
mainPane = new JTabbedPane();
|
||||||
|
|
||||||
|
sourceCodeUI = new CodeUI(watchpointMote);
|
||||||
|
JPanel sourceCodePanel = new JPanel(new BorderLayout());
|
||||||
|
sourceCodePanel.add(BorderLayout.CENTER, sourceCodeUI);
|
||||||
|
sourceCodePanel.add(BorderLayout.SOUTH, sourceCodeControl);
|
||||||
|
mainPane.addTab("Source code", null, sourceCodePanel, null); /* SOURCECODE */
|
||||||
|
|
||||||
|
|
||||||
/* Main components: assembler and C code + breakpoints (center) */
|
|
||||||
assCodeUI = new DebugUI(this.mspMote.getCPU(), true);
|
assCodeUI = new DebugUI(this.mspMote.getCPU(), true);
|
||||||
breakpointsUI = new BreakpointsUI(breakpoints, this);
|
for (Component c: assCodeUI.getComponents()) {
|
||||||
sourceCodeUI = new CodeUI(breakpoints);
|
c.setBackground(Color.WHITE);
|
||||||
leftSplitPane = new JSplitPane(
|
}
|
||||||
JSplitPane.HORIZONTAL_SPLIT,
|
mainPane.addTab("Instructions", null, assCodeUI, null);
|
||||||
new JScrollPane(assCodeUI),
|
|
||||||
new JScrollPane(breakpointsUI)
|
|
||||||
);
|
|
||||||
leftSplitPane.setOneTouchExpandable(true);
|
|
||||||
leftSplitPane.setDividerLocation(0.0);
|
|
||||||
rightSplitPane = new JSplitPane(
|
|
||||||
JSplitPane.HORIZONTAL_SPLIT,
|
|
||||||
leftSplitPane,
|
|
||||||
new JScrollPane(sourceCodeUI)
|
|
||||||
);
|
|
||||||
rightSplitPane.setOneTouchExpandable(true);
|
|
||||||
rightSplitPane.setDividerLocation(0.0);
|
|
||||||
|
|
||||||
add(BorderLayout.NORTH, browseBox);
|
breakpointsUI = new BreakpointsUI(mspMote, this);
|
||||||
add(BorderLayout.CENTER, rightSplitPane);
|
mainPane.addTab("Breakpoints", null, breakpointsUI, "Right-click source code to add"); /* BREAKPOINTS */
|
||||||
add(BorderLayout.SOUTH, controlPanel);
|
|
||||||
|
add(BorderLayout.CENTER, mainPane);
|
||||||
|
|
||||||
|
/* Listen for breakpoint changes */
|
||||||
|
watchpointMote.addWatchpointListener(watchpointListener = new WatchpointListener() {
|
||||||
|
public void watchpointTriggered(final Watchpoint watchpoint) {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
logger.info("Watchpoint triggered: " + watchpoint);
|
||||||
|
if (simulation.isRunning()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
breakpointsUI.selectBreakpoint(watchpoint);
|
||||||
|
sourceCodeUI.updateBreakpoints();
|
||||||
|
showCurrentPC();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public void watchpointsChanged() {
|
||||||
|
sourceCodeUI.updateBreakpoints();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
/* Observe when simulation starts/stops */
|
/* Observe when simulation starts/stops */
|
||||||
simulation.addObserver(simObserver = new Observer() {
|
simulation.addObserver(simObserver = new Observer() {
|
||||||
public void update(Observable obs, Object obj) {
|
public void update(Observable obs, Object obj) {
|
||||||
if (!simulation.isRunning()) {
|
if (!simulation.isRunning()) {
|
||||||
stepAction.setEnabled(true);
|
stepAction.setEnabled(true);
|
||||||
updateInfo();
|
showCurrentPC();
|
||||||
} else {
|
} else {
|
||||||
stepAction.setEnabled(false);
|
stepAction.setEnabled(false);
|
||||||
}
|
}
|
||||||
@ -208,7 +220,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setSize(750, 500);
|
setSize(750, 500);
|
||||||
updateInfo();
|
showCurrentPC();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFileComboBox() {
|
private void updateFileComboBox() {
|
||||||
@ -221,25 +233,12 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
fileComboBox.setSelectedIndex(0);
|
fileComboBox.setSelectedIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void displaySourceFile(File file, final int line) {
|
public void displaySourceFile(final File file, final int line, final boolean markCurrent) {
|
||||||
if (file != null &&
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
sourceCodeUI.displayedFile != null &&
|
public void run() {
|
||||||
file.compareTo(sourceCodeUI.displayedFile) == 0) {
|
mainPane.setSelectedIndex(SOURCECODE); /* code */
|
||||||
/* No need to reload source file */
|
sourceCodeUI.displayNewCode(file, line, markCurrent);
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
}});
|
||||||
public void run() {
|
|
||||||
sourceCodeUI.displayLine(line);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load source file from disk */
|
|
||||||
String[] codeData = readTextFile(file);
|
|
||||||
if (codeData == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sourceCodeUI.displayNewCode(file, codeData, line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sourceFileSelectionChanged() {
|
private void sourceFileSelectionChanged() {
|
||||||
@ -249,32 +248,40 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
File selectedFile = sourceFiles[index-1];
|
File selectedFile = sourceFiles[index-1];
|
||||||
displaySourceFile(selectedFile, -1);
|
displaySourceFile(selectedFile, -1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateInfo() {
|
private void showCurrentPC() {
|
||||||
/* Instructions */
|
/* Instructions */
|
||||||
assCodeUI.updateRegs();
|
assCodeUI.updateRegs();
|
||||||
assCodeUI.repaint();
|
assCodeUI.repaint();
|
||||||
|
|
||||||
/* Source */
|
/* Source */
|
||||||
updateCurrentSourceCodeFile();
|
updateCurrentSourceCodeFile();
|
||||||
if (currentCodeFile == null) {
|
File file = currentCodeFile;
|
||||||
|
Integer line = currentLineNumber;
|
||||||
|
if (file == null || line == null) {
|
||||||
currentFileAction.setEnabled(false);
|
currentFileAction.setEnabled(false);
|
||||||
currentFileAction.putValue(Action.NAME, "[unknown]");
|
currentFileAction.putValue(Action.NAME, "[unknown]");
|
||||||
currentFileAction.putValue(Action.SHORT_DESCRIPTION, null);
|
currentFileAction.putValue(Action.SHORT_DESCRIPTION, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentFileAction.setEnabled(true);
|
currentFileAction.setEnabled(true);
|
||||||
currentFileAction.putValue(Action.NAME, currentCodeFile.getName() + ":" + currentLineNumber);
|
currentFileAction.putValue(Action.NAME, file.getName() + ":" + line);
|
||||||
currentFileAction.putValue(Action.SHORT_DESCRIPTION, currentCodeFile.getAbsolutePath() + ":" + currentLineNumber);
|
currentFileAction.putValue(Action.SHORT_DESCRIPTION, file.getAbsolutePath() + ":" + line);
|
||||||
fileComboBox.setSelectedItem(currentCodeFile.getName());
|
fileComboBox.setSelectedItem(file.getName());
|
||||||
|
|
||||||
displaySourceFile(currentCodeFile, currentLineNumber);
|
displaySourceFile(file, line, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closePlugin() {
|
public void closePlugin() {
|
||||||
|
watchpointMote.removeWatchpointListener(watchpointListener);
|
||||||
|
watchpointListener = null;
|
||||||
|
|
||||||
simulation.deleteObserver(simObserver);
|
simulation.deleteObserver(simObserver);
|
||||||
|
simObserver = null;
|
||||||
|
|
||||||
|
/* TODO XXX Unregister breakpoints? */
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCurrentSourceCodeFile() {
|
private void updateCurrentSourceCodeFile() {
|
||||||
@ -285,8 +292,12 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
if (debug == null) {
|
if (debug == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DebugInfo debugInfo = debug.getDebugInfo(mspMote.getCPU().reg[MSP430.PC]);
|
int pc = mspMote.getCPU().getPC();
|
||||||
|
DebugInfo debugInfo = debug.getDebugInfo(pc);
|
||||||
if (debugInfo == null) {
|
if (debugInfo == null) {
|
||||||
|
if (pc != 0) {
|
||||||
|
logger.warn("No sourcecode info at " + String.format("0x%04x", mspMote.getCPU().getPC()));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,6 +332,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
private void tryMapDebugInfo() {
|
private void tryMapDebugInfo() {
|
||||||
final String[] debugFiles;
|
final String[] debugFiles;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
ELFDebug debug = ((MspMoteType)mspMote.getType()).getELF().getDebug();
|
ELFDebug debug = ((MspMoteType)mspMote.getType()).getELF().getDebug();
|
||||||
debugFiles = debug != null ? debug.getSourceFiles() : null;
|
debugFiles = debug != null ? debug.getSourceFiles() : null;
|
||||||
if (debugFiles == null) {
|
if (debugFiles == null) {
|
||||||
@ -343,7 +355,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
"\"Next File\" proceeds to the next source file in the debug info.\n\n" +
|
"\"Next File\" proceeds to the next source file in the debug info.\n\n" +
|
||||||
debugFiles[counter] + " (" + (counter+1) + '/' + debugFiles.length + ')',
|
debugFiles[counter] + " (" + (counter+1) + '/' + debugFiles.length + ')',
|
||||||
"Select source file to locate", JOptionPane.YES_NO_CANCEL_OPTION,
|
"Select source file to locate", JOptionPane.YES_NO_CANCEL_OPTION,
|
||||||
JOptionPane.QUESTION_MESSAGE, null,
|
JOptionPane.QUESTION_MESSAGE, null,
|
||||||
new String[] { "Next File", "Locate File", "Cancel"}, "Next File");
|
new String[] { "Next File", "Locate File", "Cancel"}, "Next File");
|
||||||
if (n == JOptionPane.CANCEL_OPTION || n == JOptionPane.CLOSED_OPTION) {
|
if (n == JOptionPane.CANCEL_OPTION || n == JOptionPane.CLOSED_OPTION) {
|
||||||
return null;
|
return null;
|
||||||
@ -421,14 +433,14 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
optionPane.setOptions(new String[] { "OK" });
|
optionPane.setOptions(new String[] { "OK" });
|
||||||
optionPane.setInitialValue("OK");
|
optionPane.setInitialValue("OK");
|
||||||
JDialog dialog = optionPane.createDialog(
|
JDialog dialog = optionPane.createDialog(
|
||||||
GUI.getTopParentContainer(),
|
GUI.getTopParentContainer(),
|
||||||
"Mapping debug info to real sources");
|
"Mapping debug info to real sources");
|
||||||
dialog.setVisible(true);
|
dialog.setVisible(true);
|
||||||
|
|
||||||
replace = replaceInput.getText();
|
replace = replaceInput.getText();
|
||||||
replacement = replacementInput.getText();
|
replacement = replacementInput.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
replace = replace.replace('\\', '/');
|
replace = replace.replace('\\', '/');
|
||||||
replacement = replacement.replace('\\', '/');
|
replacement = replacement.replace('\\', '/');
|
||||||
return new String[] { replace, replacement };
|
return new String[] { replace, replacement };
|
||||||
@ -444,7 +456,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
updateFileComboBox();
|
updateFileComboBox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File[] getSourceFiles(MspMote mote, String[] map) {
|
private static File[] getSourceFiles(MspMote mote, String[] map) {
|
||||||
final String[] sourceFiles;
|
final String[] sourceFiles;
|
||||||
try {
|
try {
|
||||||
@ -465,7 +477,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that files exist */
|
/* Verify that files exist */
|
||||||
ArrayList<File> existing = new ArrayList<File>();
|
ArrayList<File> existing = new ArrayList<File>();
|
||||||
for (String sourceFile: sourceFiles) {
|
for (String sourceFile: sourceFiles) {
|
||||||
@ -512,7 +524,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
"Make sure the source files were not moved after the firmware compilation.\n" +
|
"Make sure the source files were not moved after the firmware compilation.\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"If you want to manually locate the sources, click \"Map\" button.",
|
"If you want to manually locate the sources, click \"Map\" button.",
|
||||||
"No source files found",
|
"No source files found",
|
||||||
JOptionPane.WARNING_MESSAGE);
|
JOptionPane.WARNING_MESSAGE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -530,7 +542,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
}
|
}
|
||||||
sorted.add(index, file);
|
sorted.add(index, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add Contiki source first */
|
/* Add Contiki source first */
|
||||||
if (contikiSource != null && contikiSource.exists()) {
|
if (contikiSource != null && contikiSource.exists()) {
|
||||||
sorted.add(0, contikiSource);
|
sorted.add(0, contikiSource);
|
||||||
@ -539,63 +551,21 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
return sorted.toArray(new File[0]);
|
return sorted.toArray(new File[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to open and read given text file.
|
|
||||||
*
|
|
||||||
* @param file File
|
|
||||||
* @return Line-by-line text in file
|
|
||||||
*/
|
|
||||||
public static String[] readTextFile(File file) {
|
|
||||||
if (GUI.isVisualizedInApplet()) {
|
|
||||||
/* Download from web server instead */
|
|
||||||
String path = file.getPath();
|
|
||||||
|
|
||||||
/* Extract Contiki build path */
|
|
||||||
String contikiBuildPath = GUI.getExternalToolsSetting("PATH_CONTIKI_BUILD");
|
|
||||||
String contikiWebPath = GUI.getExternalToolsSetting("PATH_CONTIKI_WEB");
|
|
||||||
|
|
||||||
if (!path.startsWith(contikiBuildPath)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
/* Replace Contiki parent path with web server code base */
|
|
||||||
path = contikiWebPath + '/' + path.substring(contikiBuildPath.length());
|
|
||||||
path = path.replace('\\', '/');
|
|
||||||
URL url = new URL(GUI.getAppletCodeBase(), path);
|
|
||||||
String data = StringUtils.loadFromURL(url);
|
|
||||||
return data!=null?data.split("\n"):null;
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
logger.warn("Failure to read source code: " + e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String data = StringUtils.loadFromFile(file);
|
|
||||||
return data!=null?data.split("\n"):null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<Element> getConfigXML() {
|
public Collection<Element> getConfigXML() {
|
||||||
Vector<Element> config = new Vector<Element>();
|
ArrayList<Element> config = new ArrayList<Element>();
|
||||||
Element element;
|
Element element;
|
||||||
|
|
||||||
element = new Element("split_1");
|
element = new Element("tab");
|
||||||
element.addContent("" + leftSplitPane.getDividerLocation());
|
element.addContent("" + mainPane.getSelectedIndex());
|
||||||
config.add(element);
|
config.add(element);
|
||||||
|
|
||||||
element = new Element("split_2");
|
|
||||||
element.addContent("" + rightSplitPane.getDividerLocation());
|
|
||||||
config.add(element);
|
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||||
for (Element element : configXML) {
|
for (Element element : configXML) {
|
||||||
if (element.getName().equals("split_1")) {
|
if (element.getName().equals("tab")) {
|
||||||
leftSplitPane.setDividerLocation(Integer.parseInt(element.getText()));
|
mainPane.setSelectedIndex(Integer.parseInt(element.getText()));
|
||||||
} else if (element.getName().equals("split_2")) {
|
|
||||||
rightSplitPane.setDividerLocation(Integer.parseInt(element.getText()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -608,11 +578,11 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
if (currentCodeFile == null) {
|
if (currentCodeFile == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
displaySourceFile(currentCodeFile, currentLineNumber);
|
displaySourceFile(currentCodeFile, currentLineNumber, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private AbstractAction mapAction = new AbstractAction("Map") {
|
private AbstractAction mapAction = new AbstractAction("Locate sources") {
|
||||||
private static final long serialVersionUID = -3929432830596292495L;
|
private static final long serialVersionUID = -3929432830596292495L;
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@ -622,14 +592,13 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||||||
|
|
||||||
private AbstractAction stepAction = new AbstractAction("Step instruction") {
|
private AbstractAction stepAction = new AbstractAction("Step instruction") {
|
||||||
private static final long serialVersionUID = 3520750710757816575L;
|
private static final long serialVersionUID = 3520750710757816575L;
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
try {
|
try {
|
||||||
mspMote.getCPU().stepInstructions(1);
|
mspMote.getCPU().stepInstructions(1);
|
||||||
} catch (EmulationException ex) {
|
} catch (EmulationException ex) {
|
||||||
logger.fatal("Error: ", ex);
|
logger.fatal("Error: ", ex);
|
||||||
}
|
}
|
||||||
updateInfo();
|
showCurrentPC();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id: CodeUI.java,v 1.8 2009/09/23 08:16:06 fros4943 Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.sics.cooja.util;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.swing.Action;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.text.JTextComponent;
|
||||||
|
|
||||||
|
import jsyntaxpane.SyntaxDocument;
|
||||||
|
import jsyntaxpane.actions.DefaultSyntaxAction;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import se.sics.cooja.WatchpointMote;
|
||||||
|
|
||||||
|
public class JSyntaxAddBreakpoint extends DefaultSyntaxAction {
|
||||||
|
private static Logger logger = Logger.getLogger(JSyntaxAddBreakpoint.class);
|
||||||
|
|
||||||
|
public JSyntaxAddBreakpoint() {
|
||||||
|
super("addbreakpoint");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
JMenuItem menuItem = (JMenuItem) e.getSource();
|
||||||
|
Action action = menuItem.getAction();
|
||||||
|
WatchpointMote watchpointMote = (WatchpointMote) action.getValue("WatchpointMote");
|
||||||
|
if (watchpointMote == null) {
|
||||||
|
logger.warn("Error: No source, cannot configure breakpoint");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = (File) action.getValue("WatchpointFile");
|
||||||
|
Integer line = (Integer) action.getValue("WatchpointLine");
|
||||||
|
Integer address = (Integer) action.getValue("WatchpointAddress");
|
||||||
|
if (file == null || line == null || address == null) {
|
||||||
|
logger.warn("Error: Bad breakpoint info, cannot add breakpoint");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
watchpointMote.addBreakpoint(file, line, address);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id: CodeUI.java,v 1.8 2009/09/23 08:16:06 fros4943 Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.sics.cooja.util;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.swing.Action;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
|
||||||
|
import jsyntaxpane.actions.DefaultSyntaxAction;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import se.sics.cooja.Watchpoint;
|
||||||
|
import se.sics.cooja.WatchpointMote;
|
||||||
|
|
||||||
|
public class JSyntaxRemoveBreakpoint extends DefaultSyntaxAction {
|
||||||
|
private static Logger logger = Logger.getLogger(JSyntaxRemoveBreakpoint.class);
|
||||||
|
|
||||||
|
public JSyntaxRemoveBreakpoint() {
|
||||||
|
super("removebreakpoint");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
JMenuItem menuItem = (JMenuItem) e.getSource();
|
||||||
|
Action action = menuItem.getAction();
|
||||||
|
WatchpointMote watchpointMote = (WatchpointMote) action.getValue("WatchpointMote");
|
||||||
|
if (watchpointMote == null) {
|
||||||
|
logger.warn("Error: No source, cannot configure breakpoint");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = (File) action.getValue("WatchpointFile");
|
||||||
|
Integer line = (Integer) action.getValue("WatchpointLine");
|
||||||
|
Integer address = (Integer) action.getValue("WatchpointAddress");
|
||||||
|
if (file == null || line == null || address == null) {
|
||||||
|
logger.warn("Error: Bad breakpoint info, cannot remove breakpoint");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Watchpoint w: watchpointMote.getBreakpoints()) {
|
||||||
|
if (file.equals(w.getCodeFile()) && line.equals(w.getLineNumber()) && address.equals(w.getExecutableAddress())) {
|
||||||
|
watchpointMote.removeBreakpoint(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user