/*
* $Id$
*
* Copyright (C) 2003-2015 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.bjorne;
import org.jnode.driver.console.CompletionInfo;
import org.jnode.shell.CommandLine;
import org.jnode.shell.CommandShell;
import org.jnode.shell.CommandThread;
import org.jnode.shell.ShellException;
import org.jnode.shell.ShellFailureException;
import org.jnode.shell.ShellInvocationException;
import org.jnode.shell.help.CompletionException;
import org.jnode.shell.io.CommandIO;
import org.jnode.shell.io.CommandIOHolder;
import org.jnode.vm.VmExit;
public class SimpleCommandNode extends CommandNode implements BjorneCompletable {
private BjorneToken[] assignments;
private final BjorneToken[] words;
public SimpleCommandNode(int nodeType, BjorneToken[] words) {
super(nodeType);
this.words = words;
}
public void setAssignments(BjorneToken[] assignments) {
this.assignments = assignments;
}
public BjorneToken[] getWords() {
return words;
}
public BjorneToken[] getAssignments() {
return assignments;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("SimpleCommand{").append(super.toString());
if (assignments != null) {
sb.append(",assignments=");
appendArray(sb, assignments);
}
if (words != null) {
sb.append(",words=");
appendArray(sb, words);
}
sb.append('}');
return sb.toString();
}
@Override
public int execute(final BjorneContext context) throws ShellException {
CommandIOHolder[] holders = null;
int rc;
try {
BjorneToken[] words = getWords();
if (words.length == 0) {
// No command to run: assignments are done in the shell's context
context.performAssignments(assignments);
// Surprisingly, we still need to perform the redirections
BjorneContext childContext = new BjorneContext(context);
childContext.evaluateRedirections(getRedirects());
rc = 0;
} else {
// FIXME ... strictly speaking, alias substitution should be performed
// before "applying the grammatical rules" (i.e. parsing).
words = context.substituteAliases(words);
CommandLine command = context.buildCommandLine(words);
// Assignments and redirections are done in the command's context
BjorneContext childContext = new BjorneContext(context);
childContext.performAssignments(assignments);
holders = childContext.evaluateRedirections(getRedirects());
CommandIO[] ios = new CommandIO[holders.length];
for (int i = 0; i < ios.length; i++) {
ios[i] = holders[i].getIO();
}
if ((getFlags() & BjorneInterpreter.FLAG_ASYNC) != 0) {
throw new ShellFailureException(
"asynchronous execution (&) not implemented yet");
} else {
rc = childContext.execute(command, ios);
}
}
} catch (BjorneControlException ex) {
if (ex.getControl() == BjorneInterpreter.BRANCH_EXIT) {
throw new VmExit(ex.getCount());
} else {
throw ex;
}
} catch (ShellInvocationException ex) {
context.getShell().resolvePrintStream(context.getIO(2)).println(ex.getMessage());
rc = 1;
} finally {
if (holders != null) {
for (CommandIOHolder holder : holders) {
holder.close();
}
}
}
if ((getFlags() & BjorneInterpreter.FLAG_BANG) != 0) {
rc = (rc == 0) ? -1 : 0;
}
context.setLastReturnCode(rc);
return rc;
}
public CommandThread fork(CommandShell shell, BjorneContext context)
throws ShellException {
if (words.length > 0) {
CommandLine command = context.buildCommandLine(words);
command.setStreams(context.getIOs());
return shell.invokeAsynchronous(command);
} else {
return null;
}
}
@Override
public void complete(CompletionInfo completions, BjorneContext context, CommandShell shell,
boolean argumentAnticipated)
throws CompletionException {
try {
CommandLine command = context.buildCommandLine(words);
String commandName = command.getCommandName();
if (commandName != null && BjorneInterpreter.isBuiltin(commandName)) {
BjorneBuiltinCommandInfo commandInfo =
BjorneInterpreter.BUILTINS.get(commandName).buildCommandInfo(context);
command.setCommandInfo(commandInfo);
}
command.setArgumentAnticipated(argumentAnticipated);
command.complete(completions, shell);
} catch (ShellException ex) {
throw new CompletionException("Shell exception", ex);
}
}
}