From: <jo...@us...> - 2008-03-09 00:52:17
|
Revision: 160 http://mspsim.svn.sourceforge.net/mspsim/?rev=160&view=rev Author: joxe Date: 2008-03-08 16:52:15 -0800 (Sat, 08 Mar 2008) Log Message: ----------- added some more command types to support pipe implementation. Modified Paths: -------------- mspsim/CHANGE_LOG.txt mspsim/se/sics/mspsim/cli/CommandContext.java mspsim/se/sics/mspsim/cli/CommandHandler.java mspsim/se/sics/mspsim/cli/DebugCommands.java mspsim/se/sics/mspsim/core/MSP430.java mspsim/se/sics/mspsim/core/MSP430Core.java mspsim/se/sics/mspsim/platform/GenericNode.java mspsim/se/sics/mspsim/platform/sky/SkyNode.java mspsim/se/sics/mspsim/ui/DebugUI.java Added Paths: ----------- mspsim/se/sics/mspsim/cli/AsyncCommand.java mspsim/se/sics/mspsim/cli/BasicAsyncCommand.java mspsim/se/sics/mspsim/cli/BasicLineCommand.java Removed Paths: ------------- mspsim/se/sics/mspsim/util/BasicCommand.java mspsim/se/sics/mspsim/util/Command.java mspsim/se/sics/mspsim/util/CommandBundle.java mspsim/se/sics/mspsim/util/CommandContext.java mspsim/se/sics/mspsim/util/CommandHandler.java mspsim/se/sics/mspsim/util/CommandParser.java mspsim/se/sics/mspsim/util/DebugCommands.java Modified: mspsim/CHANGE_LOG.txt =================================================================== --- mspsim/CHANGE_LOG.txt 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/CHANGE_LOG.txt 2008-03-09 00:52:15 UTC (rev 160) @@ -1,6 +1,7 @@ 0.85 Changes: - fixed multiplier to handle the different modes better. +- 0.84 Changes: Added: mspsim/se/sics/mspsim/cli/AsyncCommand.java =================================================================== --- mspsim/se/sics/mspsim/cli/AsyncCommand.java (rev 0) +++ mspsim/se/sics/mspsim/cli/AsyncCommand.java 2008-03-09 00:52:15 UTC (rev 160) @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2007, 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. + * + * This file is part of MSPSim. + * + * $Id: $ + * + * ----------------------------------------------------------------- + * + * AsyncCommand - a command that will continue its execution after it + * returns from the executeCommand method. + * + * Author : Joakim Eriksson + * Created : 9 mar 2008 + * Updated : $Date:$ + * $Revision:$ + */ +package se.sics.mspsim.cli; + +/** + * @author joakim + * + */ +public interface AsyncCommand extends Command { + public void stopCommand(CommandContext context); +} Added: mspsim/se/sics/mspsim/cli/BasicAsyncCommand.java =================================================================== --- mspsim/se/sics/mspsim/cli/BasicAsyncCommand.java (rev 0) +++ mspsim/se/sics/mspsim/cli/BasicAsyncCommand.java 2008-03-09 00:52:15 UTC (rev 160) @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2007, 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. + * + * This file is part of MSPSim. + * + * $Id: $ + * + * ----------------------------------------------------------------- + * + * BasicAsyncCommand + * + * Author : Joakim Eriksson + * Created : 9 mar 2008 + * Updated : $Date:$ + * $Revision:$ + */ +package se.sics.mspsim.cli; + +/** + * @author joakim + * + */ +public abstract class BasicAsyncCommand extends BasicCommand implements + AsyncCommand { + + public BasicAsyncCommand(String cmdHelp, String argHelp) { + super(cmdHelp, argHelp); + } +} Added: mspsim/se/sics/mspsim/cli/BasicLineCommand.java =================================================================== --- mspsim/se/sics/mspsim/cli/BasicLineCommand.java (rev 0) +++ mspsim/se/sics/mspsim/cli/BasicLineCommand.java 2008-03-09 00:52:15 UTC (rev 160) @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2007, 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. + * + * This file is part of MSPSim. + * + * $Id: $ + * + * ----------------------------------------------------------------- + * + * BasicLineCommand + * + * Author : Joakim Eriksson + * Created : 9 mar 2008 + * Updated : $Date:$ + * $Revision:$ + */ +package se.sics.mspsim.cli; + +/** + * @author joakim + * + */ +public abstract class BasicLineCommand extends BasicAsyncCommand implements + LineListener { + + public BasicLineCommand(String cmdHelp, String argHelp) { + super(cmdHelp, argHelp); + } +} Modified: mspsim/se/sics/mspsim/cli/CommandContext.java =================================================================== --- mspsim/se/sics/mspsim/cli/CommandContext.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/cli/CommandContext.java 2008-03-09 00:52:15 UTC (rev 160) @@ -10,19 +10,27 @@ private String[] args; private MapTable mapTable; + private int pid; + public final PrintStream out; public final PrintStream err; public final InputStream in; + private CommandContext nextCommand; + public CommandContext(MapTable table, String[] args, - InputStream in, PrintStream out, PrintStream err) { + int pid, InputStream in, PrintStream out, PrintStream err) { this.args = args; this.out = out; this.err = err; this.in = in; + this.pid = pid; mapTable = table; } + public int getPID() { + return pid; + } /** * exit needs to be called as soon as the command is completed (or stopped). Modified: mspsim/se/sics/mspsim/cli/CommandHandler.java =================================================================== --- mspsim/se/sics/mspsim/cli/CommandHandler.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/cli/CommandHandler.java 2008-03-09 00:52:15 UTC (rev 160) @@ -18,60 +18,60 @@ private Hashtable<String, Command> commands = new Hashtable<String, Command>(); private boolean exit; private boolean workaround = false; - + private BufferedReader inReader; private InputStream in; private PrintStream out; private PrintStream err; private MapTable mapTable; private ComponentRegistry registry; - + public CommandHandler() { exit = false; inReader = new BufferedReader(new InputStreamReader(in = System.in)); out = System.out; err = System.err; - + registerCommand("help", new Command() { public int executeCommand(CommandContext context) { if (context.getArgumentCount() == 0) { - context.out.println("Available commands:"); - for(Map.Entry entry: commands.entrySet()) { - String name = (String) entry.getKey(); - Command command = (Command) entry.getValue(); - CommandContext cc = new CommandContext(mapTable, new String[] { - name - }, context.in, context.out, context.err); - String prefix = ' ' + name + ' ' + command.getArgumentHelp(cc); - String helpText = command.getCommandHelp(cc); - int n; - if (helpText != null && (n = helpText.indexOf('\n')) > 0) { - helpText = helpText.substring(0, n); - } - context.out.print(prefix); - if (prefix.length() < 8) { - context.out.print('\t'); - } - if (prefix.length() < 16) { - context.out.print('\t'); - } - context.out.println("\t " + helpText); - } - return 0; - } + context.out.println("Available commands:"); + for(Map.Entry entry: commands.entrySet()) { + String name = (String) entry.getKey(); + Command command = (Command) entry.getValue(); + CommandContext cc = new CommandContext(mapTable, new String[] { + name + }, 0, context.in, context.out, context.err); + String prefix = ' ' + name + ' ' + command.getArgumentHelp(cc); + String helpText = command.getCommandHelp(cc); + int n; + if (helpText != null && (n = helpText.indexOf('\n')) > 0) { + helpText = helpText.substring(0, n); + } + context.out.print(prefix); + if (prefix.length() < 8) { + context.out.print('\t'); + } + if (prefix.length() < 16) { + context.out.print('\t'); + } + context.out.println("\t " + helpText); + } + return 0; + } - String cmd = context.getArgument(0); - Command command = commands.get(cmd); - if (command != null) { - CommandContext cc = new CommandContext(mapTable, new String[] { - cmd - }, context.in, context.out, context.err); - context.out.println(cmd + ' ' + command.getArgumentHelp(cc)); - context.out.println(" " + command.getCommandHelp(cc)); - return 0; - } - context.err.println("Error: unknown command '" + cmd + '\''); - return 1; + String cmd = context.getArgument(0); + Command command = commands.get(cmd); + if (command != null) { + CommandContext cc = new CommandContext(mapTable, new String[] { + cmd + }, 0, context.in, context.out, context.err); + context.out.println(cmd + ' ' + command.getArgumentHelp(cc)); + context.out.println(" " + command.getCommandHelp(cc)); + return 0; + } + context.err.println("Error: unknown command '" + cmd + '\''); + return 1; } public String getArgumentHelp(CommandContext context) { return "<command>"; @@ -87,62 +87,63 @@ } }); } - + // Add it to the hashtable (overwriting anything there) public void registerCommand(String cmd, Command command) { commands.put(cmd, command); } - + private String readLine(BufferedReader inReader2) throws IOException { if (workaround) { - StringBuilder str = new StringBuilder(); - while(true) { - if (inReader2.ready()) { - int c = inReader2.read(); - if (c == '\n') { - return str.toString(); + StringBuilder str = new StringBuilder(); + while(true) { + if (inReader2.ready()) { + int c = inReader2.read(); + if (c == '\n') { + return str.toString(); + } + if (c != '\r') { + str.append((char)c); + } + } else { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } } - if (c != '\r') { - str.append((char)c); - } - } else { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - throw new InterruptedIOException(); - } } - } } else { return inReader2.readLine(); } } - + public void run() { while(!exit) { - try { + try { out.print(">"); out.flush(); String line = readLine(inReader);//.readLine(); if (line != null && line.length() > 0) { - String[][] parts = CommandParser.parseLine(line); - if(parts.length > 0) { - // TODO add support for pipes - String[] args = parts[0]; - Command cmd = commands.get(args[0]); - if (cmd == null) { - out.println("Error: Unknown command " + args[0]); - } else { - CommandContext cc = new CommandContext(mapTable, args, in, out, err); - try { - cmd.executeCommand(cc); - } catch (Exception e) { - err.println("Error: Command failed: " + e.getMessage()); - e.printStackTrace(err); - } - } - } + String[][] parts = CommandParser.parseLine(line); + if(parts.length > 0) { + checkCommands(parts); + // TODO add support for pipes + String[] args = parts[0]; + Command cmd = commands.get(args[0]); + if (cmd == null) { + out.println("Error: Unknown command " + args[0]); + } else { + CommandContext cc = new CommandContext(mapTable, args, 0, in, out, err); + try { + cmd.executeCommand(cc); + } catch (Exception e) { + err.println("Error: Command failed: " + e.getMessage()); + e.printStackTrace(err); + } + } + } } } catch (IOException e) { e.printStackTrace(); @@ -152,6 +153,17 @@ } } + private int checkCommands(String[][] cmds) { + for (int i = 0; i < cmds.length; i++) { + Command command = commands.get(cmds[i][0]); + if (i > 0 && command != null && !(command instanceof LineListener)) { + System.out.println("CLI: Error " + cmds[i][0] + " does not take input"); + return -1; + } + } + return 0; + } + public void setComponentRegistry(ComponentRegistry registry) { this.registry = registry; } @@ -159,14 +171,14 @@ public void setWorkaround(boolean w) { workaround = w; } - + public void start() { mapTable = (MapTable) registry.getComponent(MapTable.class); Object[] commandBundles = registry.getAllComponents(CommandBundle.class); if (commandBundles != null) { for (int i = 0, n = commandBundles.length; i < n; i++) { - ((CommandBundle) commandBundles[i]).setupCommands(registry, this); + ((CommandBundle) commandBundles[i]).setupCommands(registry, this); } } new Thread(this, "cmd").start(); Modified: mspsim/se/sics/mspsim/cli/DebugCommands.java =================================================================== --- mspsim/se/sics/mspsim/cli/DebugCommands.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/cli/DebugCommands.java 2008-03-09 00:52:15 UTC (rev 160) @@ -77,8 +77,10 @@ } }); - ch.registerCommand("watch", new Command() { + ch.registerCommand("watch", + new BasicAsyncCommand("adds a write watch to a given address or symbol", "<address or symbol>") { int mode = 0; + int address = 0; public int executeCommand(final CommandContext context) { int baddr = context.getArgumentAsAddress(0); if (baddr == -1) { @@ -91,7 +93,7 @@ mode = 1; } } - cpu.setBreakPoint(baddr, + cpu.setBreakPoint(address = baddr, new CPUMonitor() { public void cpuAction(int type, int adr, int data) { if (mode == 0) { @@ -108,14 +110,10 @@ context.out.println("Watch set at: " + baddr); return 0; } - - public String getArgumentHelp(CommandContext context) { - return "<address or symbol>"; + + public void stopCommand(CommandContext context) { + cpu.clearBreakPoint(address); } - - public String getCommandHelp(CommandContext context) { - return "adds a write watch to a given address or symbol"; - } }); ch.registerCommand("clear", new Command() { @@ -197,6 +195,17 @@ return 0; } }); + // Does nothign yet... TODO!!! + ch.registerCommand("grep", new BasicLineCommand("grep", "regexp") { + public void lineRead(String line) { + } + public void stopCommand(CommandContext context) { + } + public int executeCommand(CommandContext context) { + return 0; + } + + }); } } } Modified: mspsim/se/sics/mspsim/core/MSP430.java =================================================================== --- mspsim/se/sics/mspsim/core/MSP430.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/core/MSP430.java 2008-03-09 00:52:15 UTC (rev 160) @@ -1,4 +1,4 @@ -/** + /** * Copyright (c) 2007, Swedish Institute of Computer Science. * All rights reserved. * Modified: mspsim/se/sics/mspsim/core/MSP430Core.java =================================================================== --- mspsim/se/sics/mspsim/core/MSP430Core.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/core/MSP430Core.java 2008-03-09 00:52:15 UTC (rev 160) @@ -252,9 +252,13 @@ breakPoints[address] = mon; } - public boolean hasBreakpoint(int address) { + public boolean hasBreakPoint(int address) { return breakPoints[address] != null; } + + public void clearBreakPoint(int address) { + breakPoints[address] = null; + } public void setRegisterWriteMonitor(int r, CPUMonitor mon) { regWriteMonitors[r] = mon; Modified: mspsim/se/sics/mspsim/platform/GenericNode.java =================================================================== --- mspsim/se/sics/mspsim/platform/GenericNode.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/platform/GenericNode.java 2008-03-09 00:52:15 UTC (rev 160) @@ -41,14 +41,14 @@ import java.io.File; import java.io.IOException; +import se.sics.mspsim.cli.CommandHandler; +import se.sics.mspsim.cli.DebugCommands; import se.sics.mspsim.core.Chip; import se.sics.mspsim.core.MSP430; import se.sics.mspsim.extutil.highlight.HighlightSourceViewer; import se.sics.mspsim.extutil.jfreechart.DataChart; import se.sics.mspsim.ui.ControlUI; -import se.sics.mspsim.util.CommandHandler; import se.sics.mspsim.util.ComponentRegistry; -import se.sics.mspsim.util.DebugCommands; import se.sics.mspsim.util.ELF; import se.sics.mspsim.util.IHexReader; import se.sics.mspsim.util.MapTable; Modified: mspsim/se/sics/mspsim/platform/sky/SkyNode.java =================================================================== --- mspsim/se/sics/mspsim/platform/sky/SkyNode.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/platform/sky/SkyNode.java 2008-03-09 00:52:15 UTC (rev 160) @@ -46,6 +46,8 @@ import se.sics.mspsim.chip.CC2420; import se.sics.mspsim.chip.M25P80; import se.sics.mspsim.chip.PacketListener; +import se.sics.mspsim.cli.CommandHandler; +import se.sics.mspsim.cli.DebugCommands; import se.sics.mspsim.core.CPUMonitor; import se.sics.mspsim.core.Chip; import se.sics.mspsim.core.IOPort; @@ -60,10 +62,8 @@ import se.sics.mspsim.extutil.jfreechart.DataSourceSampler; import se.sics.mspsim.platform.GenericNode; import se.sics.mspsim.ui.ControlUI; -import se.sics.mspsim.util.CommandHandler; import se.sics.mspsim.util.ComponentRegistry; import se.sics.mspsim.util.DataSource; -import se.sics.mspsim.util.DebugCommands; import se.sics.mspsim.util.ELF; import se.sics.mspsim.util.IHexReader; import se.sics.mspsim.util.MapTable; Modified: mspsim/se/sics/mspsim/ui/DebugUI.java =================================================================== --- mspsim/se/sics/mspsim/ui/DebugUI.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/ui/DebugUI.java 2008-03-09 00:52:15 UTC (rev 160) @@ -186,7 +186,7 @@ s += "; " + i.getFunction(); } pos = i.getPos(); - if (cpu.hasBreakpoint(pos)) { + if (cpu.hasBreakPoint(pos)) { s = "*B " + s; } else { s = " " + s; Deleted: mspsim/se/sics/mspsim/util/BasicCommand.java =================================================================== --- mspsim/se/sics/mspsim/util/BasicCommand.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/util/BasicCommand.java 2008-03-09 00:52:15 UTC (rev 160) @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2008, 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. - * - * This file is part of MSPSim. - * - * $Id$ - * - * ----------------------------------------------------------------- - * - * BasicCommand - * - * Author : Joakim Eriksson, Niclas Finne - * Created : Mon Feb 11 21:28:00 2008 - * Updated : $Date: 2007/10/21 21:17:34 $ - * $Revision: 1.3 $ - */ - -package se.sics.mspsim.util; - -public abstract class BasicCommand implements Command { - - private String argumentHelp; - private String commandHelp; - - public BasicCommand(String cmdHelp, String argHelp) { - commandHelp = cmdHelp; - argumentHelp = argHelp; - } - - public String getArgumentHelp(CommandContext context) { - return argumentHelp; - } - - public String getCommandHelp(CommandContext context) { - return commandHelp; - } - -} Deleted: mspsim/se/sics/mspsim/util/Command.java =================================================================== --- mspsim/se/sics/mspsim/util/Command.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/util/Command.java 2008-03-09 00:52:15 UTC (rev 160) @@ -1,7 +0,0 @@ -package se.sics.mspsim.util; - -public interface Command { - public int executeCommand(CommandContext context); - public String getCommandHelp(CommandContext context); - public String getArgumentHelp(CommandContext context); -} Deleted: mspsim/se/sics/mspsim/util/CommandBundle.java =================================================================== --- mspsim/se/sics/mspsim/util/CommandBundle.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/util/CommandBundle.java 2008-03-09 00:52:15 UTC (rev 160) @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2008, 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. - * - * This file is part of MSPSim. - * - * $Id$ - * - * ----------------------------------------------------------------- - * - * CommandBundle - * - * Author : Joakim Eriksson, Niclas Finne - * Created : Mon Feb 11 21:28:00 2008 - * Updated : $Date: 2007/10/21 21:17:34 $ - * $Revision: 1.3 $ - */ - -package se.sics.mspsim.util; - -public interface CommandBundle { - - public void setupCommands(ComponentRegistry registry, CommandHandler handler); - -} Deleted: mspsim/se/sics/mspsim/util/CommandContext.java =================================================================== --- mspsim/se/sics/mspsim/util/CommandContext.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/util/CommandContext.java 2008-03-09 00:52:15 UTC (rev 160) @@ -1,74 +0,0 @@ -package se.sics.mspsim.util; - -import java.io.InputStream; -import java.io.PrintStream; - - -public class CommandContext { - - private String[] args; - private MapTable mapTable; - public final PrintStream out; - public final PrintStream err; - public final InputStream in; - - public CommandContext(MapTable table, String[] args, - InputStream in, PrintStream out, PrintStream err) { - this.args = args; - this.out = out; - this.err = err; - this.in = in; - mapTable = table; - } - - public int getArgumentCount() { - return args.length - 1; - } - - public String getArgument(int index) { - return args[index + 1]; - } - - public MapTable getMapTable() { - return mapTable; - } - - public String getCommand() { - return args[0]; - } - - public int getArgumentAsAddress(int index) { - String adr = getArgument(index); - if (adr == null || adr.length() == 0) return 0; - adr = adr.trim(); - if (adr.charAt(0) == '$') { - try { - return Integer.parseInt(adr.substring(1), 16); - } catch (Exception e) { - err.println("Illegal hex number format: " + adr); - } - } else if (Character.isDigit(adr.charAt(0))) { - try { - return Integer.parseInt(adr); - } catch (Exception e) { - err.println("Illegal number format: " + adr); - } - } else { - // Assume that it is a symbol - if (mapTable != null) { - return mapTable.getFunctionAddress(adr); - } - } - return 0; - } - - public int getArgumentAsInt(int i) { - try { - return Integer.parseInt(getArgument(i)); - } catch (Exception e) { - err.println("Illegal number format: " + getArgument(i)); - } - return 0; - } - -} Deleted: mspsim/se/sics/mspsim/util/CommandHandler.java =================================================================== --- mspsim/se/sics/mspsim/util/CommandHandler.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/util/CommandHandler.java 2008-03-09 00:52:15 UTC (rev 160) @@ -1,170 +0,0 @@ -package se.sics.mspsim.util; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.InterruptedIOException; -import java.io.PrintStream; -import java.util.Hashtable; -import java.util.Map; - -public class CommandHandler implements ActiveComponent, Runnable { - - private Hashtable<String, Command> commands = new Hashtable<String, Command>(); - private boolean exit; - private boolean workaround = false; - - private BufferedReader inReader; - private InputStream in; - private PrintStream out; - private PrintStream err; - private MapTable mapTable; - private ComponentRegistry registry; - - public CommandHandler() { - exit = false; - inReader = new BufferedReader(new InputStreamReader(in = System.in)); - out = System.out; - err = System.err; - - registerCommand("help", new Command() { - public int executeCommand(CommandContext context) { - if (context.getArgumentCount() == 0) { - context.out.println("Available commands:"); - for(Map.Entry entry: commands.entrySet()) { - String name = (String) entry.getKey(); - Command command = (Command) entry.getValue(); - CommandContext cc = new CommandContext(mapTable, new String[] { - name - }, context.in, context.out, context.err); - String prefix = ' ' + name + ' ' + command.getArgumentHelp(cc); - String helpText = command.getCommandHelp(cc); - int n; - if (helpText != null && (n = helpText.indexOf('\n')) > 0) { - helpText = helpText.substring(0, n); - } - context.out.print(prefix); - if (prefix.length() < 8) { - context.out.print('\t'); - } - if (prefix.length() < 16) { - context.out.print('\t'); - } - context.out.println("\t " + helpText); - } - return 0; - } - - String cmd = context.getArgument(0); - Command command = commands.get(cmd); - if (command != null) { - CommandContext cc = new CommandContext(mapTable, new String[] { - cmd - }, context.in, context.out, context.err); - context.out.println(cmd + ' ' + command.getArgumentHelp(cc)); - context.out.println(" " + command.getCommandHelp(cc)); - return 0; - } - context.err.println("Error: unknown command '" + cmd + '\''); - return 1; - } - public String getArgumentHelp(CommandContext context) { - return "<command>"; - } - public String getCommandHelp(CommandContext context) { - return "shows help for the specified command"; - } - }); - registerCommand("workaround", new BasicCommand("", "") { - public int executeCommand(CommandContext context) { - workaround = true; - return 0; - } - }); - } - - // Add it to the hashtable (overwriting anything there) - public void registerCommand(String cmd, Command command) { - commands.put(cmd, command); - } - - - private String readLine(BufferedReader inReader2) throws IOException { - if (workaround) { - StringBuilder str = new StringBuilder(); - while(true) { - if (inReader2.ready()) { - int c = inReader2.read(); - if (c == '\n') { - return str.toString(); - } - if (c != '\r') { - str.append((char)c); - } - } else { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - throw new InterruptedIOException(); - } - } - } - } else { - return inReader2.readLine(); - } - } - - public void run() { - while(!exit) { - try { - out.print(">"); - out.flush(); - String line = readLine(inReader);//.readLine(); - if (line != null && line.length() > 0) { - String[][] parts = CommandParser.parseLine(line); - if(parts.length > 0) { - // TODO add support for pipes - String[] args = parts[0]; - Command cmd = commands.get(args[0]); - if (cmd == null) { - out.println("Error: Unknown command " + args[0]); - } else { - CommandContext cc = new CommandContext(mapTable, args, in, out, err); - try { - cmd.executeCommand(cc); - } catch (Exception e) { - err.println("Error: Command failed: " + e.getMessage()); - e.printStackTrace(err); - } - } - } - } - } catch (IOException e) { - e.printStackTrace(); - err.println("Command line tool exiting..."); - exit = true; - } - } - } - - public void setComponentRegistry(ComponentRegistry registry) { - this.registry = registry; - } - - public void setWorkaround(boolean w) { - workaround = w; - } - - public void start() { - mapTable = (MapTable) registry.getComponent(MapTable.class); - - Object[] commandBundles = registry.getAllComponents(CommandBundle.class); - if (commandBundles != null) { - for (int i = 0, n = commandBundles.length; i < n; i++) { - ((CommandBundle) commandBundles[i]).setupCommands(registry, this); - } - } - new Thread(this, "cmd").start(); - } -} Deleted: mspsim/se/sics/mspsim/util/CommandParser.java =================================================================== --- mspsim/se/sics/mspsim/util/CommandParser.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/util/CommandParser.java 2008-03-09 00:52:15 UTC (rev 160) @@ -1,179 +0,0 @@ -/** - * Copyright (c) 2008, 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. - * - * This file is part of MSPSim. - * - * ----------------------------------------------------------------- - * - * CommandParser - * - * Author : Joakim Eriksson, Niclas Finne - * Created : Sun Mar 2 19:41:00 2008 - * Updated : $Date: 2007/10/21 21:17:34 $ - * $Revision: 1.3 $ - */ -package se.sics.mspsim.util; -import java.util.ArrayList; - -public class CommandParser { - - private static final int TEXT = 0; - private static final int ARG = 1; - private static final int QUOTE = 2; - - private CommandParser() { - // Prevent instances of this class - } - - public static String[][] parseLine(String line) { - ArrayList<String[]> list = new ArrayList<String[]>(); - ArrayList<String> args = new ArrayList<String>(); - StringBuilder sb = null; - int state = TEXT; - int index = 0; - char quote = 0; - - for (int i = 0, n = line.length(); i < n; i++) { - char c = line.charAt(i); - if (c <= 32) { - // White space - if (state == ARG) { - if (sb == null) { - args.add(line.substring(index, i)); - } else { - args.add(sb.append(line.substring(index, i)).toString()); - sb = null; - } - state = TEXT; - } - - } else { - switch (c) { - case '\\': - i++; - if (i >= n) { - throw new IllegalArgumentException("unexpected end of line"); - } - if (state == TEXT) { - state = ARG; - } else { - if (sb == null) { - sb = new StringBuilder(); - } - sb.append(line.substring(index, i - 1)); - } - index = i; - break; - case '"': - case '\'': - if (state == QUOTE) { - if (c == quote) { - // End of quote - if (sb == null) { - args.add(line.substring(index, i)); - } else { - args.add(sb.append(line.substring(index, i)).toString()); - sb = null; - } - state = TEXT; - } - } else { - // Start new quote - if (state != TEXT) { - if (sb == null) { - args.add(line.substring(index, i)); - } else { - args.add(sb.append(line.substring(index, i)).toString()); - sb = null; - } - } - index = i + 1; - state = QUOTE; - quote = c; - } - break; - case '|': - if (state != QUOTE) { - // PIPE - if (state == ARG) { - if (sb == null) { - args.add(line.substring(index, i)); - } else { - args.add(sb.append(line.substring(index, i)).toString()); - sb = null; - } - } - state = TEXT; - if (args.size() == 0) { - throw new IllegalArgumentException("empty command"); - } - list.add(args.toArray(new String[args.size()])); - args.clear(); - } - break; - default: - if (state == TEXT) { - index = i; - state = ARG; - } - break; - } - } - } - if (state == QUOTE) { - throw new IllegalArgumentException("unexpected end of line"); - } - if (state == ARG) { - if (sb == null) { - args.add(line.substring(index)); - } else { - args.add(sb.append(line.substring(index)).toString()); - } - } - if (args.size() > 0) { - list.add(args.toArray(new String[args.size()])); - } - return list.toArray(new String[list.size()][]); - } - -// public static void main(String[] args) { -// StringBuilder sb = new StringBuilder(); -// for (int i = 0, n = args.length; i < n; i++) { -// if (i > 0) sb.append(' '); -// sb.append(args[0]); -// } -// String[][] list = parseLine(sb.toString()); -// for (int j = 0, m = list.length; j < m; j++) { -// String[] a = list[j]; -// System.out.println("PARSED LINE:"); -// for (int i = 0, n = a.length; i < n; i++) { -// System.out.println(" ARG " + (i + 1) + ": '" + a[i] + '\''); -// } -// } -// } - -} Deleted: mspsim/se/sics/mspsim/util/DebugCommands.java =================================================================== --- mspsim/se/sics/mspsim/util/DebugCommands.java 2008-03-08 08:13:09 UTC (rev 159) +++ mspsim/se/sics/mspsim/util/DebugCommands.java 2008-03-09 00:52:15 UTC (rev 160) @@ -1,217 +0,0 @@ -/** - * Copyright (c) 2008, 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. - * - * This file is part of MSPSim. - * - * $Id$ - * - * ----------------------------------------------------------------- - * - * CommandBundle - * - * Author : Joakim Eriksson, Niclas Finne - * Created : Mon Feb 11 2008 - * Updated : $Date: 2007/10/21 21:17:34 $ - * $Revision: 1.3 $ - */ -package se.sics.mspsim.util; -import se.sics.mspsim.core.CPUMonitor; -import se.sics.mspsim.core.MSP430; -import se.sics.mspsim.platform.GenericNode; - -public class DebugCommands implements CommandBundle { - - public void setupCommands(ComponentRegistry registry, CommandHandler ch) { - final MSP430 cpu = (MSP430) registry.getComponent(MSP430.class); - final ELF elf = (ELF) registry.getComponent(ELF.class); - final GenericNode node = (GenericNode) registry.getComponent("node"); - if (cpu != null) { - ch.registerCommand("break", new Command() { - public int executeCommand(final CommandContext context) { - int baddr = context.getArgumentAsAddress(0); - cpu.setBreakPoint(baddr, - new CPUMonitor() { - public void cpuAction(int type, int adr, int data) { - context.out.println("*** Break at " + adr); - } - }); - context.out.println("Breakpoint set at: " + baddr); - return 0; - } - - public String getArgumentHelp(CommandContext context) { - return "<address or symbol>"; - } - - public String getCommandHelp(CommandContext context) { - return "adds a breakpoint to a given address or symbol"; - } - }); - - ch.registerCommand("watch", new Command() { - int mode = 0; - public int executeCommand(final CommandContext context) { - int baddr = context.getArgumentAsAddress(0); - if (baddr == -1) { - context.out.println("Error: unkown symbol:" + context.getArgument(0)); - return -1; - } - if (context.getArgumentCount() > 1) { - String modeStr = context.getArgument(1); - if ("char".equals(modeStr)) { - mode = 1; - } - } - cpu.setBreakPoint(baddr, - new CPUMonitor() { - public void cpuAction(int type, int adr, int data) { - if (mode == 0) { - int pc = cpu.readRegister(0); - String adrStr = getSymOrAddr(context, adr); - String pcStr = getSymOrAddrELF(elf, pc); - context.out.println("*** Write from " + pcStr + - ": " + adrStr + " = " + data); - } else { - context.out.print((char) data); - } - } - }); - context.out.println("Watch set at: " + baddr); - return 0; - } - - public String getArgumentHelp(CommandContext context) { - return "<address or symbol>"; - } - - public String getCommandHelp(CommandContext context) { - return "adds a write watch to a given address or symbol"; - } - }); - - ch.registerCommand("clear", new Command() { - public int executeCommand(final CommandContext context) { - int baddr = context.getArgumentAsAddress(0); - cpu.setBreakPoint(baddr, null); - return 0; - } - - public String getArgumentHelp(CommandContext context) { - return "<address or symbol>"; - } - - public String getCommandHelp(CommandContext context) { - return "clears a breakpoint or watch from a given address or symbol"; - } - }); - - - - ch.registerCommand("symbol", new BasicCommand("lists matching symbold", "<regexp>") { - public int executeCommand(final CommandContext context) { - String regExp = context.getArgument(0); - MapEntry[] entries = context.getMapTable().getEntries(regExp); - for (int i = 0; i < entries.length; i++) { - MapEntry mapEntry = entries[i]; - context.out.println(" " + mapEntry.getName() + " at " + - Utils.hex16(mapEntry.getAddress())); - } - return 0; - } - }); - - if (node != null) { - ch.registerCommand("stop", new BasicCommand("stops mspsim", "") { - public int executeCommand(CommandContext context) { - node.stop(); - context.out.println("CPU stopped at: " + Utils.hex16(cpu.readRegister(0))); - return 0; - } - }); - ch.registerCommand("start", new BasicCommand("starts mspsim", "") { - public int executeCommand(CommandContext context) { - node.start(); - return 0; - } - }); - ch.registerCommand("step", new BasicCommand("singlesteps mspsim", "<number of lines>") { - public int executeCommand(CommandContext context) { - int nr = context.getArgumentCount() > 0 ? context.getArgumentAsInt(0) : 1; - while(nr-- > 0) - node.step(); - context.out.println("CPU stepped to: " + Utils.hex16(cpu.readRegister(0))); - return 0; - } - }); - ch.registerCommand("print", new BasicCommand("prints value of an address or symbol", "<address or symbol>") { - public int executeCommand(CommandContext context) { - int adr = context.getArgumentAsAddress(0); - if (adr != -1) { - context.out.println("" + context.getArgument(0) + " = " + Utils.hex16(cpu.read(adr, adr >= 0x100))); - } else { - context.out.println("unkown symbol"); - } - return 0; - } - }); - ch.registerCommand("printreg", new BasicCommand("prints value of an register", "<register>") { - public int executeCommand(CommandContext context) { - int adr = context.getArgumentAsInt(0); - context.out.println("" + context.getArgument(0) + " = " + Utils.hex16(cpu.readRegister(adr))); - return 0; - } - }); - ch.registerCommand("time", new BasicCommand("prints the elapse time and cycles", "") { - public int executeCommand(CommandContext context) { - long time = ((long)(cpu.getTimeMillis())); - context.out.println("Emulated time elapsed:" + time + "(ms) cycles: " + cpu.cycles); - return 0; - } - }); - } - } - } - - private static String getSymOrAddr(CommandContext context, int adr) { - MapEntry me = context.getMapTable().getEntry(adr); - if (me != null) { - return me.getName(); - } else { - return Utils.hex16(adr); - } - } - - private static String getSymOrAddrELF(ELF elf, int adr) { - DebugInfo me = elf.getDebugInfo(adr); - if (me != null) { - return me.toString(); - } else { - return Utils.hex16(adr); - } - } - -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |