void CollectParents(InterfaceRec* rec, const SVector<InterfaceRec*>& classes, SVector<InterfaceRec*>* out)
{
	SVector<SString> parents = rec->Parents();
	const size_t N = parents.CountItems();
	for (size_t i=0; i<N; i++) {
		const size_t Nc = classes.CountItems();
		for (size_t c=0; c<Nc; c++) {
			if (parents[i] == classes[c]->ID() || parents[i] == classes[c]->FullInterfaceName()) {
				out->AddItem(classes[c]);
			}
		}
	}
	out->AddItem(rec);
}
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;
}
void rem_binder_cleanup_func(binder_cleanup_func func)
{
	SAutolock _l(g_cleanupLock.Lock());
	size_t N = g_cleanupFuncs.CountItems();
	for (size_t i=0; i<N; i++) {
		if (g_cleanupFuncs[i] == func) {
			g_cleanupFuncs.RemoveItemsAt(i);
			i--;
			N--;
		}
	}
}
void call_binder_cleanup_funcs()
{
	SVector<binder_cleanup_func> funcs;
	{
		SAutolock _l(g_cleanupLock.Lock());
		funcs = g_cleanupFuncs;
		g_cleanupFuncs.MakeEmpty();
	}

	size_t N = funcs.CountItems();
	while (N-- > 0) {
		funcs[N]();
	}
}
status_t 
IDLStruct::SetInterfaces(SVector<InterfaceRec> interfaces)
{
	p_interfaces=interfaces;
	#ifdef STRUCTDEBUG
		bout << "<----- idlstruct.cpp -----> there are now "
			<< p_interfaces.CountItems() << " interfaces in IDLStruct\n";
	
		for (size_t index=0 ; index<interfaces.CountItems() ; index++ ) {	
			bout << "<----- idlstruct.cpp ----->		"
				<<p_interfaces.ItemAt(index).ID() << " added\n"; 
		}
	#endif		
	return B_OK;
}
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;
}
void NamespaceGenerator::EnterNamespace(const sptr<ITextOutput> stream, const SString& newNS, const SVector<SString>& newUsing)
{
	SString ns, nspart;
	int32_t pos, oldpos;
	size_t i;
	bool diff = prevNamespace != newNS;

	for (i=0; !diff && i<newUsing.CountItems(); i++) {
		diff = prevUsing.IndexOf(newUsing[i]) < 0;
	}

	if (!diff) return;

	bool haveNamespaces = false;
	
	if (prevNamespace != newNS) {
		if (prevNamespace.Length() > 0) {
			stream << endl;
			if (!haveNamespaces) {
				haveNamespaces = true;
				stream << "#if _SUPPORTS_NAMESPACE" << endl;
			}

			for (i=0; i<namespaceDepth; i++) stream << "} ";
			namespaceDepth = 0;
			stream << "// namespace " << prevNamespace << endl;
			stream << endl;
		}
		prevNamespace = newNS;
		prevUsing.MakeEmpty();
		if (prevNamespace.Length() > 0) {
			ns = newNS;
			oldpos = 0;
			while ((pos = ns.FindFirst("::", oldpos)) > 0) {
				nspart.SetTo(ns.String()+oldpos, pos-oldpos);
				if (!haveNamespaces) {
					haveNamespaces = true;
					stream << "#if _SUPPORTS_NAMESPACE" << endl;
				}
				stream << "namespace " << nspart << " {" << endl;
				oldpos = pos + 2;
				namespaceDepth++;
			}
			namespaceDepth++;
			nspart.SetTo(ns.String()+oldpos);
			if (!haveNamespaces) {
				haveNamespaces = true;
				stream << "#if _SUPPORTS_NAMESPACE" << endl;
			}
			stream << "namespace " << nspart << " {" << endl;
		} else {
			namespaceDepth = 0;
		}
	}

	if (newNS != "palmos::support" && prevUsing.IndexOf(SString("palmos::support")) < 0) {
		if (!haveNamespaces) {
			stream << "#if _SUPPORTS_NAMESPACE" << endl;
		}
		haveNamespaces = true;
		stream << "using namespace palmos::support;" << endl;
		prevUsing.AddItem(SString("palmos::support"));
	}

	for (i=0; i<newUsing.CountItems(); i++) {
		const SString& n = newUsing[i];
		if (newNS != n && prevUsing.IndexOf(n) < 0) {
			if (!haveNamespaces) {
				stream << "#if _SUPPORTS_NAMESPACE" << endl;
			}
			haveNamespaces = true;
			stream << "using namespace " << n << ";" << endl;
			prevUsing.AddItem(n);
		}
	}

	if (haveNamespaces) {
		stream << "#endif /* _SUPPORTS_NAMESPACE */" << endl;
		stream << endl;
	}
}
示例#8
0
/*
	While it's not possible to actually do it, it's possible to
	make manifest files that describe a circular dependency of
	one VM on another, and it's not okay to crash if some mean
	person does this.  So keep a list of vms that we're trying
	instantiate, and fail if it's cyclical.
*/
sptr<IBinder>
BProcess::DoInstantiate(	const SContext& context,
                            const SValue &componentInfo,
                            const SString &component,
                            SVector<SString> &vmIDs,
                            const SValue &args,
                            status_t* outError)
{
    sptr<IBinder> b;
    SValue v;
    bool found;
    size_t i, count;

//#if BUILD_TYPE == BUILD_TYPE_DEBUG
//	SContext default_context = get_default_context();
//	if (default_context.AsBinder() != context.AsBinder()) {
//		// for now, all the shell commands from the bootscript are instantiated
//		// in the system context.
//		// Weed those out (and don't do the assert)
//		SValue shellInterface("org.openbinder.tools.ICommand");
//		if (shellInterface != componentInfo["interface"]) {
//			bout << "WHOA! Instantiating component in System context! (Is this okay?)" << endl;
//			bout << "... componentInfo = " << componentInfo << endl;
//		}
//	}
//	// DbgOnlyFatalErrorIf(default_context.AsBinder() != context.AsBinder(), "Why are we instantiating in System context?");
//
//#endif

    SValue virtualMachineNameValue = componentInfo["vm"];

    // If there is no VM specified, then it's an executable file
    if (!virtualMachineNameValue.IsDefined()) {

        const SValue file = componentInfo["file"];
        if (!file.IsDefined()) {
            if (outError) *outError = B_ENTRY_NOT_FOUND;
            DbgOnlyFatalError("No file found for component");
            return NULL;
        }

        // Load the image for this package.
        sptr<ComponentImage> image = get_shared_object(file, componentInfo);

        // And now, if we found the image, instantiate the requested component,
        // using the component name, not the full ID.
        if (image != NULL) {
#if BUILD_TYPE == BUILD_TYPE_DEBUG
            const int32_t origCount = image->StrongCount();
#endif
            sptr<IBinder> obj = image->InstantiateComponent(componentInfo["local"].AsString(), context, args);
#if BUILD_TYPE == BUILD_TYPE_DEBUG
            const int32_t newCount = image->StrongCount();
            if (obj != NULL && newCount <= origCount) {
                bout << endl
                     << "***********************************************" << endl
                     << "******************* WARNING *******************" << endl
                     << "***********************************************" << endl
                     << "A component MAY not be using SPackageSptr!!!" << endl
                     << "Original image reference count was " << origCount
                     << ", the new count is " << newCount << endl
                     << "The component info is: " << componentInfo << endl
                     << endl;
            }
#endif
            if (outError) *outError = B_OK;
            return obj;
        }

        if (outError) *outError = B_ERROR;
        return NULL;
    }
    // avoid end-of-non-void-function-not-reached warning
    /* else */
#if !LIBBE_BOOTSTRAP
    {
        SString virtualMachineComponent = virtualMachineNameValue.AsString();

        SValue vmComponentInfo;
        SString vmComponentName;

        context.LookupComponent(virtualMachineComponent, &vmComponentInfo);

        // If we found a cycle, fail
        count = vmIDs.CountItems();
        for (i=0; count; i++) {
            if (vmIDs[i] == virtualMachineComponent) {
                if (outError) *outError = B_ERROR;
                return NULL;
            }
        }
        vmIDs.AddItem(virtualMachineComponent);

        // Get a running vm!
        m_imageLock.LockQuick();
        sptr<IVirtualMachine> vm = m_imageData->vms.ValueFor(virtualMachineComponent, &found);

        if (!found) {
            // Oooh.  Recursion.  Instantiate the virtual machine.
            // There's no good way of passing args through to the vm also, so pass B_UNDEFINED_VALUE
            b = this->DoInstantiate(context, vmComponentInfo, vmComponentName, vmIDs, B_UNDEFINED_VALUE, outError);
            vm = IVirtualMachine::AsInterface(b);

            ErrFatalErrorIf(vm == NULL, "could not instantiate VM");

            m_imageData->vms.AddItem(virtualMachineComponent, vm);

            vm->Init();
        }
        m_imageLock.Unlock();

        // Have the vm instantiate the object
        return vm->InstantiateComponent(componentInfo, component, args, outError);
    }
#endif
}