SValue For::Evaluate(const sptr<BShell>& parent, const sptr<ICommand>& shell, bool* outExit)
{
	SVector<SValue> args;

	for (size_t i = 0 ; i < m_words.CountItems(); i++)
	{
		bool insert_args = false;
		//bout << "WORDS [" << i << "] " << m_words[i] << endl;
		SValue expanded = Expand(shell, m_words.ItemAt(i), &insert_args);
		
		if (insert_args)
		{
			collect_arguments(expanded.AsString(), &args);
		}
		else
		{
			//bout << "adding expanded " << expanded << endl;
			args.AddItem(expanded);
		}
	}
	
	*outExit = false;
	SValue returned = SValue::Status(B_OK);
	
	for (size_t i = 0 ; i < args.CountItems() && !*outExit; i++)
	{
		//bout << "setting m_condition to be " << args.ItemAt(i) << endl;
		shell->SetProperty(SValue::String(m_condition), args.ItemAt(i));
		returned = m_dolist->Evaluate(parent, shell, outExit);
	}
	
	return returned;
}
SValue SimpleCommand::Evaluate(const sptr<BShell>& parent, const sptr<ICommand>& shell, bool* outExit)
{
//	bout << "SimpleCommand::Evaluate: " << m_command << endl;

	sptr<ICommand> command = NULL;
	bool doExit = false;
	*outExit = false;
	
	if (m_command != "" && m_command != "exit" && m_command != "return"
		&& m_command != "cd" && m_command != "." && m_command != "source")
	{
		SValue cmdName = Expand(shell, m_command);

		// If the command is actually an ICommand object,
		// run it in-place.
		// XXX This isn't quite right -- we really want
		// to spawn a copy, in which we can set our own
		// environment.
		command = ICommand::AsInterface(cmdName);

		// Not an object, try to execute by name.
		if (command == NULL) {
			command = shell->Spawn(cmdName.AsString());
		}
	
		if (command == NULL)
		{
			parent->TextError() << "bsh: " << m_command << ": command not found" << endl;
			return SValue::Status(B_NAME_NOT_FOUND);
		}
	}
	else
		command = shell;

	SValue result;

	if (m_prefix != NULL)
		result = m_prefix->Evaluate(parent, command, &doExit);
	
	if (m_suffix != NULL)
		m_suffix->Evaluate(parent, command, &doExit);
	
	SVector<SString> words;
	if (m_suffix != NULL)
		words = m_suffix->GetWords();

	// set redirects

	// build argument list
	
	ICommand::ArgList args;
	args.AddItem(SValue::String(m_command));
	
	for (size_t index = 0 ; index < words.CountItems(); index++)
	{
		bool expand = false;
		//bout << "WORDS [" << index << "] " << words[index] << endl;
		SValue expanded = Expand(shell, words.ItemAt(index), &expand);
		//bout << "WORDS [" << index << "] expaned to " << expanded << endl;
		if (expand)
		{
			collect_arguments(expanded.AsString(), &args);
		}
		else
		{
			args.AddItem(expanded);
		}
	}
		
	// only run this if we are a newly spawned command!
	if (command != shell)
	{
		result = command->Run(args);
		// This command may be a function, that could call "exit".
		*outExit = parent->ExitRequested();
	}
	else if (m_command == "exit" || m_command == "return")
	{
		result = args.CountItems() > 1 ? args[1] : SValue::Status(B_OK);
		*outExit = true;
		if (m_command == "exit") {
			parent->RequestExit();
		}
	}
	else if (m_command == "cd")
	{
		SString path;
		if (args.CountItems() > 1) {
			path = args[1].AsString();
		}
		if (path != "") {
			SString cd=shell->GetProperty(SValue::String("PWD")).AsString();
			cd.PathAppend(path, true);
			SNode node(parent->Context().Root());
			SValue dir(node.Walk(cd, (uint32_t)0));
			if (interface_cast<INode>(dir) != NULL) {
				shell->SetProperty(SValue::String("PWD"), SValue::String(cd));
				result = SValue::Status(B_OK);
			} else {
				parent->TextError() << "cd: '" << path << "' is not a directory." << endl;
				result = SValue::Status(B_BAD_VALUE);
			}
		} else {
			parent->TextError() << "cd: no directory specified." << endl;
			result = SValue::Status(B_BAD_VALUE);
		}
	}
	else if (m_command == "." || m_command == "source")
	{
		if (args.CountItems() > 1) {
			sptr<ITextInput> input;
			SString path;
			find_some_input(args[1], parent, &input, &path);
			if (input != NULL) {
				SValue oldFile = parent->GetProperty(kBSH_SCRIPT_FILE);
				SValue oldDir = parent->GetProperty(kBSH_SCRIPT_DIR);
				
				args.RemoveItemsAt(0, 2);
				args.AddItemAt(SValue::String(path), 0);
				parent->SetLastResult(SValue::String(path));
				parent->SetProperty(kBSH_SCRIPT_FILE, SValue::String(path));
				SString parentDir;
				path.PathGetParent(&parentDir);
				parent->SetProperty(kBSH_SCRIPT_DIR, SValue::String(parentDir));
				
				FunctionCommand::ArgumentHandler argHandler;
				argHandler.ApplyArgs(parent, args, true);
				sptr<Lexer> lexer = new Lexer(parent, input, parent->TextOutput(), false);
				SValue result;
				if (lexer != NULL) {
					Parser parser(parent);
					SValue result = parser.Parse(lexer);
				} else {
					parent->TextError() << m_command << ": out of memory." << endl;
					result = SValue::Status(B_NO_MEMORY);
				}
				
				argHandler.RestoreArgs(parent);
				parent->SetProperty(kBSH_SCRIPT_FILE, oldFile);
				parent->SetProperty(kBSH_SCRIPT_DIR, oldDir);
				return result;
			} else {
				parent->TextError() << m_command << ": '" << args[1] << "' is not a file." << endl;
				result = SValue::Status(B_BAD_VALUE);
			}
		} else {
			parent->TextError() << m_command << ": no file specified." << endl;
			result = SValue::Status(B_BAD_VALUE);
		}
		*outExit = parent->ExitRequested();
	}
	
	return result;
}