| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.sysml.debug; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| |
| import org.apache.commons.cli.CommandLine; |
| import org.apache.commons.cli.CommandLineParser; |
| import org.apache.commons.cli.GnuParser; |
| //import org.apache.commons.cli.HelpFormatter; |
| import org.apache.commons.cli.Option; |
| import org.apache.commons.cli.OptionBuilder; |
| import org.apache.commons.cli.Options; |
| import org.apache.commons.cli.ParseException; |
| |
| |
| /** |
| * Class implements a command line interface (CLI) for the DML language debugger |
| */ |
| public class DMLDebuggerInterface |
| { |
| |
| //SystemML debugger functionality options |
| private Options options; |
| |
| /** |
| * Constructor for a DML debugger CLI |
| */ |
| public DMLDebuggerInterface() { |
| options = new Options(); |
| } |
| |
| /** |
| * Returns the debugger CLI options |
| * @return options CLI options |
| */ |
| public Options getOptions() |
| { |
| return options; |
| } |
| |
| /** |
| * Set DML debugger CLI functionality menu |
| */ |
| @SuppressWarnings("static-access") |
| public void setOptions() |
| { |
| //add help option |
| options.addOption("h", "help", false, "list debugger functions"); |
| |
| //add run option |
| options.addOption("r", "run", false, "start your DML script"); |
| |
| //add quit option |
| options.addOption("q", "quit", false, "exit debug mode"); |
| |
| //add resume option |
| options.addOption("c", "continue", false, "continue running your DML script"); |
| |
| //add step over |
| //options.addOption("n", "next", false, "next line, stepping over function calls"); |
| |
| //add single-stepping |
| options.addOption("s", "step", false, "next line, stepping into function calls"); |
| |
| //add single-stepping |
| options.addOption("si", "stepi", false, "next runtime instruction rather than DML source lines (for advanced users)"); |
| |
| // No step return for now |
| //add step return |
| // Option stepReturn = OptionBuilder.withArgName( "function-name" ) |
| // .hasOptionalArg() |
| // .withDescription( "execute instructions associated with current function as single step") |
| // .create( "step_return" ); |
| // options.addOption(stepReturn); |
| |
| //add set breakpoint option |
| Option setBreakpoint = OptionBuilder.withLongOpt( "break" ) |
| .withArgName( "line-number" ) |
| .hasArg() |
| .withDescription( "set breakpoint at given line number" ) |
| .create( "b" ); |
| options.addOption(setBreakpoint); |
| |
| // The key assumption here is that user doesnot keep toggling breakpoints too often |
| //add delete breakpoint option |
| Option disableBreakpoint = OptionBuilder.withLongOpt( "delete" ) |
| .withArgName( "line-number" ) |
| .hasArg() |
| .withDescription( "delete breakpoint at given line number" ) |
| .create( "d" ); |
| options.addOption(disableBreakpoint); |
| |
| //add list breakpoints option |
| Option infoOption = OptionBuilder.withLongOpt( "info" ) |
| .withArgName( "[break | frame]" ) |
| .hasOptionalArgs(1) |
| .withDescription( "show all breakpoints or frames (info <break | frame>)" ) |
| .create( "i" ); |
| options.addOption(infoOption); |
| |
| //add display DML script option |
| Option displayScript = OptionBuilder.withLongOpt( "list" ) |
| .withArgName( "[next numlines] | [prev numlines] | [all]" ) |
| .hasOptionalArgs(2) |
| .withValueSeparator(' ') |
| .withDescription( "display DML script source lines. Default: numlines = 10" ) |
| .create( "l" ); |
| options.addOption(displayScript); |
| |
| //add display DML script interspersed with runtime instructions option |
| Option displayInst = OptionBuilder.withLongOpt( "listi" ) |
| .withArgName( "[next numlines] | [prev numlines] | [all]" ) |
| .hasOptionalArgs(2) |
| .withValueSeparator(' ') |
| .withDescription( "display corresponding instructions for DML script source lines. Default: numlines = 10 (for advanced users)" ) |
| .create( "li" ); |
| options.addOption(displayInst); |
| |
| //add set value of DML scalar variable option |
| Option setVar = OptionBuilder.withArgName( "varName value" ) |
| .hasArgs(2) |
| .withValueSeparator(' ') |
| .withDescription( "set value of a scalar or specified cell of a matrix variable. (Eg: \'set alpha 0.1\' or \'set A[1,2] 20\')" ) |
| .create( "set" ); |
| options.addOption(setVar); |
| |
| //add display DML matrix (or vector) variable option |
| Option displayMatrix = OptionBuilder.withLongOpt( "print" ) |
| .withArgName( "varName" ) |
| .hasArg() |
| .withDescription( "display contents of a scalar or matrix variable or rows/columns/cell of matrix. (Eg: \'p alpha\' or \'p A\' or \'p A[1,]\')" ) |
| .create( "p" ); |
| options.addOption(displayMatrix); |
| |
| Option displayTypeMatrix = OptionBuilder //.withLongOpt( "whatis" ) |
| .withArgName( "varName" ) |
| .hasArg() |
| .withDescription( "display the type (and metadata) of a variable. (Eg: \'whatis alpha\' or \'whatis A\')" ) |
| .create( "whatis" ); |
| options.addOption(displayTypeMatrix); |
| } |
| |
| /** |
| * Add new function to debugger CLI functions menu |
| * @param opt New debugging function option |
| */ |
| public void setOption(Option opt) |
| { |
| this.options.addOption(opt); |
| } |
| |
| public void writeToStandardOutput(String outputStr) { |
| System.out.print(outputStr); |
| System.out.flush(); |
| } |
| |
| public void writelnToStandardOutput(String outputStr) { |
| System.out.println(outputStr); |
| System.out.flush(); |
| } |
| |
| public void writeToStandardError(String errStr) { |
| System.err.print(errStr); |
| System.err.flush(); |
| } |
| |
| |
| public void writelnToStandardError(String errStr) { |
| System.err.println(errStr); |
| System.err.flush(); |
| } |
| |
| |
| /** |
| * Display debugger usage/help info |
| */ |
| public void getDebuggerCLI() |
| { |
| // Not using formatter because it outputs -h, -s commands. But, I still want to use GnuParser |
| // HelpFormatter debuggerUsage = new HelpFormatter(); |
| // debuggerUsage.setLongOptPrefix("-"); //Eliminates the use of "--" for alternate commands |
| // debuggerUsage.setWidth(125); //Enables readability of commands description |
| // debuggerUsage.printHelp( "SystemMLdb <command> ", "\nSystemMLdb commands:\n", options, |
| // "\n\nSystemMLdb is a prototype debugger for SystemML. There is NO warranty as " |
| // + "it is still in experimental state.\n\n" ); |
| String helpString = "SystemMLdb commands:" |
| // "usage: SystemMLdb <command>\n\nSystemMLdb commands:\n" |
| + "\nh,help list debugger functions" |
| + "\nr,run start your DML script" |
| + "\nq,quit exit debug mode" |
| + "\nc,continue continue running your DML script" |
| // |
| + "\nl,list <[next numlines] | [prev numlines] | [all]> display DML script source lines. Default: numlines = 10" |
| + "\nb,break <line-number> set breakpoint at given line number" |
| + "\nd,delete <line-number> delete breakpoint at given line number" |
| + "\ns,step next line, stepping into function calls" |
| + "\ni,info <break | frame> show all breakpoints or frames (info <break | frame>)" |
| // |
| + "\np,print <varName> display contents of a scalar or matrix variable or" |
| + "\n rows/columns/cell of matrix. (Eg: \'p alpha\' or \'p A\' or \'p A[1,]\')" |
| + "\nset <varName value> set value of a scalar or specified cell of a matrix variable. (Eg:" |
| + "\n \'set alpha 0.1\' or \'set A[1,2] 20\')" |
| + "\nwhatis <varName> display the type (and metadata) of a variable. (Eg: \'whatis alpha\'" |
| + "\n or \'whatis A\')" |
| + "\nli,listi <[next numlines] | [prev numlines] | [all]> display corresponding instructions for DML script source lines." |
| + "\n Default: numlines = 10 (for advanced users)" |
| + "\nsi,stepi next runtime instruction rather than DML source lines (for advanced" |
| + "\n users)" |
| // |
| + "\n" |
| ; |
| writelnToStandardOutput(helpString); |
| } |
| |
| /** |
| * Read, process and return command from debugger CLI |
| * @return CommandLine Current debug command (enter by user) |
| * @throws DMLDebuggerException |
| */ |
| public CommandLine getDebuggerCommand() |
| throws DMLDebuggerException |
| { |
| CommandLine cmd = null; |
| String [] args = null; |
| |
| //Display input prompt |
| writeToStandardOutput("(SystemMLdb) "); |
| BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); |
| try { |
| //read command line argument(s) |
| // To add 'up/down'-feature, use jline library |
| String line = br.readLine(); |
| if(line != null && !line.isEmpty() ) { |
| args = line.split(" "); |
| if(args[0].startsWith("-")) { |
| // So as to avoid parsing '-i' command |
| writelnToStandardError("Error reading command line arguments. Try \"help\"."); |
| return cmd; |
| } |
| args[0] = "-" + args[0]; |
| } |
| } catch (IOException ae) { |
| writelnToStandardError("Error reading command line arguments. Try \"help\"."); |
| return cmd; |
| } |
| |
| CommandLineParser CLIparser = new GnuParser(); |
| try { |
| //parse current command |
| cmd = CLIparser.parse(getOptions(), args); |
| } catch (ParseException pe) { |
| System.err.println("Undefined command (or command arguments). Try \"help\"."); |
| } |
| return cmd; |
| } |
| } |