|
From: <cr...@us...> - 2009-02-04 13:19:45
|
Revision: 4997
http://jnode.svn.sourceforge.net/jnode/?rev=4997&view=rev
Author: crawley
Date: 2009-02-04 13:19:41 +0000 (Wed, 04 Feb 2009)
Log Message:
-----------
Added hooks to shell for multi-line commands (with continuation prompts).
Implemented hooks in bjorne parser, and fixed various latent bugs with
handling of newlines.
Modified Paths:
--------------
trunk/shell/src/shell/org/jnode/shell/CommandInterpreter.java
trunk/shell/src/shell/org/jnode/shell/CommandShell.java
trunk/shell/src/shell/org/jnode/shell/DefaultInterpreter.java
trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneInterpreter.java
trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneParser.java
trunk/shell/src/test/org/jnode/test/shell/bjorne/BjorneParserTests.java
trunk/shell/src/test/org/jnode/test/shell/bjorne/bjorne-shell-tests.xml
Added Paths:
-----------
trunk/shell/src/shell/org/jnode/shell/IncompleteCommandException.java
Modified: trunk/shell/src/shell/org/jnode/shell/CommandInterpreter.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandInterpreter.java 2009-02-02 19:44:07 UTC (rev 4996)
+++ trunk/shell/src/shell/org/jnode/shell/CommandInterpreter.java 2009-02-04 13:19:41 UTC (rev 4997)
@@ -113,4 +113,18 @@
* @throws ShellException
*/
boolean help(CommandShell shell, String partial, PrintWriter pw) throws ShellException;
+
+ /**
+ * This method should <code>true</code> if the interpreter supports continuation lines. If so,
+ * it should throw IncompleteCommandException if it is expecting more input from the
+ * user. The shell will respond by reading the next line from the user, appending it
+ * to the previous input, and attempting to interpret the line again. Obviously, the
+ * interpreter needs to be side-effect free prior to throwing the exception.
+ * <p>
+ * If this method returns <code>false</code>, the interpreter will treat IncompleteCommandException
+ * as a regular ShellSyntaxException.
+ *
+ * @return <code>true</code> if this interpreter supports continuation lines.
+ */
+ boolean supportsMultilineCommands();
}
Modified: trunk/shell/src/shell/org/jnode/shell/CommandShell.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandShell.java 2009-02-02 19:44:07 UTC (rev 4996)
+++ trunk/shell/src/shell/org/jnode/shell/CommandShell.java 2009-02-04 13:19:41 UTC (rev 4997)
@@ -335,9 +335,32 @@
clearEof();
outPW.print(prompt());
readingCommand = true;
- String line = readInputLine().trim();
+ String line = readInputLine();
if (line.length() > 0) {
- runCommand(line, true, this.interpreter);
+ boolean done = false;
+ do {
+ try {
+ runCommand(line, true, this.interpreter);
+ done = true;
+ } catch (IncompleteCommandException ex) {
+ String continuation = null;
+ if (this.interpreter.supportsMultilineCommands()) {
+ String prompt = ex.getPrompt();
+ if (prompt != null) {
+ outPW.print(prompt);
+ }
+ continuation = readInputLine();
+ }
+ if (continuation == null) {
+ diagnose(ex);
+ break;
+ } else {
+ line = line + "\n" + continuation;
+ }
+ } catch (ShellException ex) {
+ diagnose(ex);
+ }
+ } while (!done);
}
if (VmSystem.isShuttingDown()) {
@@ -351,6 +374,47 @@
}
}
+ private void diagnose(ShellException ex) {
+ Throwable cause = ex.getCause();
+ // Try to turn this into something that is moderately intelligible
+ // for the common cases ...
+ if (cause != null) {
+ errPW.println(ex.getMessage());
+ if (cause instanceof CommandSyntaxException) {
+ List<Context> argErrors = ((CommandSyntaxException) cause).getArgErrors();
+ if (argErrors != null) {
+ // The parser can produce many errors as each of the alternatives
+ // in the tree are explored. The following assumes that errors
+ // produced when we get farthest along in the token stream are most
+ // likely to be the "real" errors.
+ int rightmostPos = 0;
+ for (Context context : argErrors) {
+ if (context.sourcePos > rightmostPos) {
+ rightmostPos = context.sourcePos;
+ }
+ }
+ for (Context context : argErrors) {
+ if (context.sourcePos < rightmostPos) {
+ continue;
+ }
+ if (context.token != null) {
+ errPW.println(" " + context.exception.getMessage() + ": " +
+ context.token.text);
+ } else {
+ errPW.println(" " + context.exception.getMessage() + ": " +
+ context.syntax.format());
+ }
+ }
+ }
+ } else {
+ errPW.println(cause.getMessage());
+ }
+ } else {
+ errPW.println("Shell exception: " + ex.getMessage());
+ }
+ stackTrace(ex);
+ }
+
public void configureShell() {
try {
ShellUtils.getShellManager().registerShell(this);
@@ -465,7 +529,7 @@
}
private int runCommand(String cmdLineStr, boolean interactive,
- CommandInterpreter interpreter) {
+ CommandInterpreter interpreter) throws ShellException {
if (interactive) {
clearEof();
readingCommand = false;
@@ -473,50 +537,7 @@
// for input completion
applicationHistory.set(new InputHistory());
}
- int rc = 0;
- try {
- rc = interpreter.interpret(this, cmdLineStr);
- } catch (ShellException ex) {
- Throwable cause = ex.getCause();
- // Try to turn this into something that is moderately intelligible
- // for the common cases ...
- if (cause != null) {
- errPW.println(ex.getMessage());
- if (cause instanceof CommandSyntaxException) {
- List<Context> argErrors = ((CommandSyntaxException) cause).getArgErrors();
- if (argErrors != null) {
- // The parser can produce many errors as each of the alternatives
- // in the tree are explored. The following assumes that errors
- // produced when we get farthest along in the token stream are most
- // likely to be the "real" errors.
- int rightmostPos = 0;
- for (Context context : argErrors) {
- if (context.sourcePos > rightmostPos) {
- rightmostPos = context.sourcePos;
- }
- }
- for (Context context : argErrors) {
- if (context.sourcePos < rightmostPos) {
- continue;
- }
- if (context.token != null) {
- errPW.println(" " + context.exception.getMessage() + ": " +
- context.token.text);
- } else {
- errPW.println(" " + context.exception.getMessage() + ": " +
- context.syntax.format());
- }
- }
- }
- } else {
- errPW.println(cause.getMessage());
- }
- } else {
- errPW.println("Shell exception: " + ex.getMessage());
- }
- rc = -1;
- stackTrace(ex);
- }
+ int rc = interpreter.interpret(this, cmdLineStr);
if (interactive) {
applicationHistory.set(null);
Modified: trunk/shell/src/shell/org/jnode/shell/DefaultInterpreter.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/DefaultInterpreter.java 2009-02-02 19:44:07 UTC (rev 4996)
+++ trunk/shell/src/shell/org/jnode/shell/DefaultInterpreter.java 2009-02-04 13:19:41 UTC (rev 4997)
@@ -139,6 +139,11 @@
}
@Override
+ public boolean supportsMultilineCommands() {
+ return false;
+ }
+
+ @Override
public int interpret(CommandShell shell, File file) throws ShellException {
try {
return interpret(shell, new FileReader(file));
Added: trunk/shell/src/shell/org/jnode/shell/IncompleteCommandException.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/IncompleteCommandException.java (rev 0)
+++ trunk/shell/src/shell/org/jnode/shell/IncompleteCommandException.java 2009-02-04 13:19:41 UTC (rev 4997)
@@ -0,0 +1,36 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2009 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package org.jnode.shell;
+
+public class IncompleteCommandException extends ShellSyntaxException {
+
+ private static final long serialVersionUID = 3710602404013731870L;
+
+ private final String prompt;
+
+ public IncompleteCommandException(String msg, String prompt) {
+ super(msg);
+ this.prompt = prompt;
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneInterpreter.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneInterpreter.java 2009-02-02 19:44:07 UTC (rev 4996)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneInterpreter.java 2009-02-04 13:19:41 UTC (rev 4997)
@@ -49,6 +49,7 @@
import org.jnode.shell.CommandShell;
import org.jnode.shell.CommandThread;
import org.jnode.shell.Completable;
+import org.jnode.shell.IncompleteCommandException;
import org.jnode.shell.ShellException;
import org.jnode.shell.ShellFailureException;
import org.jnode.shell.ShellSyntaxException;
@@ -188,7 +189,7 @@
public Completable parsePartial(CommandShell shell, String partial) throws ShellSyntaxException {
bindShell(shell);
BjorneTokenizer tokens = new BjorneTokenizer(partial);
- final CommandNode tree = new BjorneParser(tokens).parse();
+ final CommandNode tree = new BjorneParser(tokens, "> ").parse();
if (tree instanceof BjorneCompletable) {
return new Completable() {
@Override
@@ -228,7 +229,7 @@
myContext.setStream(1, new CommandOutput(capture), true);
}
BjorneTokenizer tokens = new BjorneTokenizer(command);
- CommandNode tree = new BjorneParser(tokens).parse();
+ CommandNode tree = new BjorneParser(tokens, "> ").parse();
if (tree == null) {
// An empty command line
return 0;
@@ -242,6 +243,11 @@
}
return tree.execute((BjorneContext) myContext);
}
+
+ @Override
+ public boolean supportsMultilineCommands() {
+ return true;
+ }
@Override
public int interpret(CommandShell shell, Reader reader) throws ShellException {
@@ -251,24 +257,34 @@
String line;
int rc = 0;
while ((line = br.readLine()) != null) {
- try {
- rc = interpret(shell, line, null, false);
- } catch (BjorneControlException ex) {
- switch (ex.getControl()) {
+ boolean done = false;
+ do {
+ try {
+ rc = interpret(shell, line, null, false);
+ done = true;
+ } catch (BjorneControlException ex) {
+ switch (ex.getControl()) {
case BjorneInterpreter.BRANCH_EXIT:
// The script will exit immediately
return ex.getCount();
case BjorneInterpreter.BRANCH_BREAK:
throw new ShellSyntaxException(
- "'break' has been executed in an inappropriate context");
+ "'break' has been executed in an inappropriate context");
case BjorneInterpreter.BRANCH_CONTINUE:
throw new ShellSyntaxException(
- "'continue' has been executed in an inappropriate context");
+ "'continue' has been executed in an inappropriate context");
case BjorneInterpreter.BRANCH_RETURN:
throw new ShellSyntaxException(
- "'return' has been executed in an inappropriate context");
+ "'return' has been executed in an inappropriate context");
+ }
+ } catch (IncompleteCommandException ex) {
+ String continuation = br.readLine();
+ if (continuation == null) {
+ throw ex;
+ }
+ line = line + "\n" + continuation;
}
- }
+ } while (!done);
}
return rc;
} catch (IOException ex) {
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneParser.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneParser.java 2009-02-02 19:44:07 UTC (rev 4996)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneParser.java 2009-02-04 13:19:41 UTC (rev 4997)
@@ -82,14 +82,18 @@
import java.util.LinkedList;
import java.util.List;
+import org.jnode.shell.IncompleteCommandException;
import org.jnode.shell.ShellFailureException;
import org.jnode.shell.ShellSyntaxException;
public class BjorneParser {
private final BjorneTokenizer tokens;
+
+ private final String continuationPrompt;
- public BjorneParser(BjorneTokenizer tokens) {
+ public BjorneParser(BjorneTokenizer tokens, String continuationPrompt) {
this.tokens = tokens;
+ this.continuationPrompt = continuationPrompt;
}
/**
@@ -174,6 +178,7 @@
}
private CommandNode parseOptAndOr() throws ShellSyntaxException {
+ skipLineBreaks();
switch (tokens.peek(RULE_1_CONTEXT).getTokenType()) {
case TOK_LBRACE:
case TOK_LPAREN:
@@ -349,9 +354,9 @@
return null;
}
tokens.next();
- if (tokens.next().getTokenType() != TOK_RPAREN) {
- throw new ShellSyntaxException(
- "expected matching ')' in function_definition");
+ int tt = tokens.next().getTokenType();
+ if (tt != TOK_RPAREN) {
+ syntaxError("expected matching ')' in function_definition", tt);
}
skipLineBreaks();
return new FunctionDefinitionNode(fname, parseFunctionBody());
@@ -412,8 +417,8 @@
io = token;
token = tokens.next();
}
- int tokenType = token.getTokenType();
- switch (tokenType) {
+ int tt = token.getTokenType();
+ switch (tt) {
case TOK_LESS:
case TOK_GREAT:
case TOK_DGREAT:
@@ -422,15 +427,17 @@
case TOK_LESSGREAT:
case TOK_CLOBBER:
arg = tokens.next();
- if (arg.getTokenType() != TOK_WORD) {
- throw new ShellSyntaxException("expected a filename after " + token);
+ tt = arg.getTokenType();
+ if (tt != TOK_WORD) {
+ syntaxError("expected a filename after " + token, tt);
}
break;
case TOK_DLESS:
case TOK_DLESSDASH:
arg = tokens.next();
+ tt = arg.getTokenType();
if (arg.getTokenType() != TOK_WORD) {
- throw new ShellSyntaxException("expected a here-end marker " + token);
+ syntaxError("expected a here-end marker " + token, tt);
}
// TODO ... need to grab the HERE document ...
break;
@@ -439,7 +446,7 @@
}
// (The corresponding token type and redirection type values are the
// same ...)
- return new RedirectionNode(tokenType, io, arg);
+ return new RedirectionNode(tt, io, arg);
}
private RedirectionNode[] parseOptRedirects() throws ShellSyntaxException {
@@ -472,8 +479,9 @@
private CommandNode parseSubshell() throws ShellSyntaxException {
tokens.next();
CommandNode compoundList = parseCompoundList();
- if (tokens.next().getTokenType() != TOK_RPAREN) {
- throw new ShellSyntaxException("expected ')'");
+ int tt = tokens.next().getTokenType();
+ if (tt != TOK_RPAREN) {
+ syntaxError("expected ')'", tt);
}
compoundList.setNodeType(CMD_SUBSHELL);
return compoundList;
@@ -486,12 +494,14 @@
LOOP:
while (command != null) {
commands.add(command);
- skipLineBreaks();
switch (tokens.peek().getTokenType()) {
case TOK_SEMI:
break;
+ case TOK_END_OF_LINE:
+ break;
case TOK_AMP:
command.setFlag(FLAG_ASYNC);
+ break;
default:
break LOOP;
}
@@ -504,8 +514,9 @@
private CommandNode parseBraceGroup() throws ShellSyntaxException {
tokens.next();
CommandNode compoundList = parseCompoundList();
- if (tokens.peek().getTokenType() != TOK_RBRACE) {
- throw new ShellSyntaxException("expected '}'");
+ int tt = tokens.peek().getTokenType();
+ if (tt != TOK_RBRACE) {
+ syntaxError("expected '}'", tt);
}
compoundList.setNodeType(CMD_BRACE_GROUP);
return compoundList;
@@ -516,8 +527,9 @@
BjorneToken word = tokens.next();
List<CaseItemNode> caseItems = new LinkedList<CaseItemNode>();
skipLineBreaks();
- if (tokens.next(RULE_6_CONTEXT).getTokenType() != TOK_IN) {
- throw new ShellSyntaxException("expected 'in' in case_clause");
+ int tt = tokens.next(RULE_6_CONTEXT).getTokenType();
+ if (tt != TOK_IN) {
+ syntaxError("expected 'in' in case_clause", tt);
}
skipLineBreaks();
BjorneToken token = tokens.peek(RULE_1_CONTEXT);
@@ -525,13 +537,13 @@
caseItems.add(parseCaseItem());
skipLineBreaks();
token = tokens.peek(RULE_1_CONTEXT);
- if (token.getTokenType() == TOK_DSEMI) {
+ tt = token.getTokenType();
+ if (tt == TOK_DSEMI) {
tokens.next();
skipLineBreaks();
token = tokens.peek(RULE_1_CONTEXT);
- } else if (token.getTokenType() != TOK_ESAC) {
- throw new ShellSyntaxException(
- "expected ';;' or 'esac' after case_item");
+ } else if (tt != TOK_ESAC) {
+ syntaxError("expected ';;' or 'esac' after case_item", tt);
}
}
tokens.next();
@@ -548,9 +560,9 @@
token = tokens.next();
}
BjorneToken[] pattern = parsePattern();
- if (tokens.next().getTokenType() != TOK_RPAREN) {
- throw new ShellSyntaxException(
- "expected ')' after pattern in case_item");
+ int tt = tokens.next().getTokenType();
+ if (tt != TOK_RPAREN) {
+ syntaxError("expected ')' after pattern in case_item", tt);
}
CommandNode body = null;
skipLineBreaks();
@@ -567,9 +579,9 @@
private BjorneToken[] parsePattern() throws ShellSyntaxException {
List<BjorneToken> pattern = new LinkedList<BjorneToken>();
while (true) {
- BjorneToken token = tokens.next();
- if (token.getTokenType() != TOK_WORD) {
- throw new ShellSyntaxException("expected WORD in pattern");
+ int tt = tokens.next().getTokenType();
+ if (tt != TOK_WORD) {
+ syntaxError("expected WORD in pattern", tt);
}
if (tokens.peek().getTokenType() != TOK_BAR) {
break;
@@ -582,8 +594,9 @@
private ForCommandNode parseForCommand() throws ShellSyntaxException {
tokens.next();
BjorneToken var = tokens.next(RULE_5_CONTEXT);
- if (var.getTokenType() != TOK_NAME) {
- throw new ShellSyntaxException("expected a NAME following 'for'");
+ int tt = var.getTokenType();
+ if (tt != TOK_NAME) {
+ syntaxError("expected a NAME following 'for'", tt);
}
skipLineBreaks();
List<BjorneToken> words = new LinkedList<BjorneToken>();
@@ -596,10 +609,10 @@
word = tokens.peek();
}
if (words.isEmpty()) {
- throw new ShellSyntaxException(
- "expected a wordlist following 'in'");
+ syntaxError("expected a wordlist following 'in'", word.getTokenType());
}
- switch (tokens.peek().getTokenType()) {
+ tt = tokens.peek().getTokenType();
+ switch (tt) {
case TOK_SEMI:
tokens.next();
skipLineBreaks();
@@ -608,7 +621,7 @@
skipLineBreaks();
break;
default:
- throw new ShellSyntaxException("expected a ';' following wordlist");
+ syntaxError("expected a ';' following wordlist", tt);
}
}
return new ForCommandNode(var,
@@ -616,13 +629,16 @@
}
private CommandNode parseDoGroup() throws ShellSyntaxException {
- BjorneToken token = tokens.next(RULE_1_CONTEXT);
- if (token.getTokenType() != TOK_DO) {
- throw new ShellSyntaxException("expected the 'do' of a do_group");
+ skipLineBreaks();
+ int tt = tokens.next(RULE_1_CONTEXT).getTokenType();
+ if (tt != TOK_DO) {
+ syntaxError("expected the 'do' of a do_group", tt);
}
CommandNode body = parseCompoundList();
- if (tokens.next(RULE_1_CONTEXT).getTokenType() != TOK_DONE) {
- throw new ShellSyntaxException("expected a command or 'done'");
+ skipLineBreaks();
+ tt = tokens.next(RULE_1_CONTEXT).getTokenType();
+ if (tt != TOK_DONE) {
+ syntaxError("expected a command or 'done'", tt);
}
return body;
}
@@ -644,23 +660,30 @@
private IfCommandNode parseIfCommand() throws ShellSyntaxException {
tokens.next();
CommandNode cond = parseCompoundList();
- if (tokens.next(RULE_1_CONTEXT).getTokenType() != TOK_THEN) {
- throw new ShellSyntaxException("expected a 'then' in if_clause");
+ skipLineBreaks();
+ int tt = tokens.next(RULE_1_CONTEXT).getTokenType();
+ if (tt != TOK_THEN) {
+ syntaxError("expected a 'then' in if_clause", tt);
}
CommandNode thenPart = parseCompoundList();
CommandNode elsePart = parseOptElsePart();
- if (tokens.next(RULE_1_CONTEXT).getTokenType() != TOK_FI) {
- throw new ShellSyntaxException("expected an 'elif', 'else' or 'fi'");
+ skipLineBreaks();
+ tt = tokens.next(RULE_1_CONTEXT).getTokenType();
+ if (tt != TOK_FI) {
+ syntaxError("expected an 'elif', 'else' or 'fi'", tt);
}
return new IfCommandNode(CMD_IF, cond, thenPart, elsePart);
}
private CommandNode parseOptElsePart() throws ShellSyntaxException {
+ skipLineBreaks();
switch (tokens.next(RULE_1_CONTEXT).getTokenType()) {
case TOK_ELIF:
CommandNode cond = parseCompoundList();
- if (tokens.next(RULE_1_CONTEXT).getTokenType() != TOK_THEN) {
- throw new ShellSyntaxException("expected a 'then' in else_part");
+ skipLineBreaks();
+ int tt = tokens.next(RULE_1_CONTEXT).getTokenType();
+ if (tt != TOK_THEN) {
+ syntaxError("expected a 'then' in else_part", tt);
}
return new IfCommandNode(CMD_ELIF, cond, parseCompoundList(),
parseOptElsePart());
@@ -671,6 +694,15 @@
return null;
}
}
+
+ private void syntaxError(String msg, int tt) throws ShellSyntaxException {
+ if (tt == TOK_END_OF_STREAM) {
+ throw new IncompleteCommandException(msg, continuationPrompt);
+ } else {
+ System.err.println("tt is " + tt);
+ throw new ShellSyntaxException(msg);
+ }
+ }
private void skipLineBreaks() {
while (tokens.peek().getTokenType() == TOK_END_OF_LINE) {
Modified: trunk/shell/src/test/org/jnode/test/shell/bjorne/BjorneParserTests.java
===================================================================
--- trunk/shell/src/test/org/jnode/test/shell/bjorne/BjorneParserTests.java 2009-02-02 19:44:07 UTC (rev 4996)
+++ trunk/shell/src/test/org/jnode/test/shell/bjorne/BjorneParserTests.java 2009-02-04 13:19:41 UTC (rev 4997)
@@ -31,7 +31,7 @@
private static final boolean DEBUG = true;
public void testParser() {
- new BjorneParser(new BjorneTokenizer(""));
+ new BjorneParser(new BjorneTokenizer(""), null);
}
public void test1() throws ShellException {
@@ -147,7 +147,7 @@
}
private String doTest(String input) throws ShellException {
- BjorneParser p = new BjorneParser(new BjorneTokenizer(input, DEBUG));
+ BjorneParser p = new BjorneParser(new BjorneTokenizer(input, DEBUG), null);
String res = p.parse().toString();
if (DEBUG) {
System.err.println(res);
Modified: trunk/shell/src/test/org/jnode/test/shell/bjorne/bjorne-shell-tests.xml
===================================================================
--- trunk/shell/src/test/org/jnode/test/shell/bjorne/bjorne-shell-tests.xml 2009-02-02 19:44:07 UTC (rev 4996)
+++ trunk/shell/src/test/org/jnode/test/shell/bjorne/bjorne-shell-tests.xml 2009-02-04 13:19:41 UTC (rev 4997)
@@ -63,6 +63,19 @@
<rc>0</rc>
</testSpec>
<testSpec>
+ <title>if ... then ... fi multi-line</title>
+ <command>test</command>
+ <runMode>AS_SCRIPT</runMode>
+ <script>#!bjorne
+if true
+then echo HI
+fi
+ </script>
+ <output>HI
+</output>
+ <rc>0</rc>
+ </testSpec>
+ <testSpec>
<title>if ... then ... else ... fi</title>
<command>test</command>
<runMode>AS_SCRIPT</runMode>
@@ -76,6 +89,25 @@
<rc>0</rc>
</testSpec>
<testSpec>
+ <title>if ... then ... else ... fi multi-line</title>
+ <command>test</command>
+ <runMode>AS_SCRIPT</runMode>
+ <script>#!bjorne
+if true ;
+then echo HI ;
+else echo HO;
+fi
+if false
+then echo HI
+else echo HO
+fi
+ </script>
+ <output>HI
+HO
+</output>
+ <rc>0</rc>
+ </testSpec>
+ <testSpec>
<title>if ... then ... elif ... else ... fi</title>
<command>test</command>
<runMode>AS_SCRIPT</runMode>
@@ -91,6 +123,38 @@
<rc>0</rc>
</testSpec>
<testSpec>
+ <title>if ... then ... elif ... else ... fi multi-line</title>
+ <command>test</command>
+ <runMode>AS_SCRIPT</runMode>
+ <script>#!bjorne
+if true ;
+then echo HI ;
+elif false ;
+then echo HO ;
+else
+echo HUM;
+fi
+if false ;
+then echo HI ;
+elif true ;
+then
+echo HO ;
+else echo HUM;
+fi
+if false
+then echo HI
+elif false
+then echo HO
+else echo HUM
+fi
+ </script>
+ <output>HI
+HO
+HUM
+</output>
+ <rc>0</rc>
+ </testSpec>
+ <testSpec>
<title>while ... do ... done</title>
<command>test</command>
<runMode>AS_SCRIPT</runMode>
@@ -113,6 +177,31 @@
<rc>0</rc>
</testSpec>
<testSpec>
+ <title>while ... do ... done multi-line</title>
+ <command>test</command>
+ <runMode>AS_SCRIPT</runMode>
+ <script>#!bjorne
+A=5
+while expr $A != 0 ;
+do echo A is $A ;
+A=`expr $A - 1`;
+done
+ </script>
+ <output>1
+A is 5
+1
+A is 4
+1
+A is 3
+1
+A is 2
+1
+A is 1
+0
+</output>
+ <rc>0</rc>
+ </testSpec>
+ <testSpec>
<title>while ... do ... break ... done</title>
<command>test</command>
<runMode>AS_SCRIPT</runMode>
@@ -136,6 +225,33 @@
<rc>0</rc>
</testSpec>
<testSpec>
+ <title>while ... do ... break ... done multi-line</title>
+ <command>test</command>
+ <runMode>AS_SCRIPT</runMode>
+ <script>#!bjorne
+ A=5
+ while expr $A != 0
+ do
+ echo A is $A
+ if expr $A = 2 ; then break ; fi ; A=`expr $A - 1`
+ done
+ </script>
+ <output>1
+A is 5
+0
+1
+A is 4
+0
+1
+A is 3
+0
+1
+A is 2
+1
+</output>
+ <rc>0</rc>
+ </testSpec>
+ <testSpec>
<title>${...} expansions</title>
<command>test</command>
<runMode>AS_SCRIPT</runMode>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|