void langbind::iostreamfilter( proc::ExecContext* execContext, const std::string& protocol, const std::string& proc, const std::string& ifl, std::size_t ib, const std::string& ofl, std::size_t ob, std::istream& is, std::ostream& os)
{
	BufferStruct buf( ib, ob);
	const proc::ProcessorProviderInterface* provider = execContext->provider();
		
	if (proc.size() == 0 || proc == "-")
	{
		LOG_TRACE << "Start executing filter";
		Filter flt = getFilter( provider, ifl, ofl);
		if (!flt.inputfilter().get()) throw std::runtime_error( "input filter not found");
		if (!flt.outputfilter().get()) throw std::runtime_error( "output filter not found");
		flt.outputfilter()->setOutputChunkSize( buf.outsize);

		// ... no command specified -> we simply map the input through the
		//	input/output filters specified:
		if (ifl.empty() && ofl.empty()) throw std::runtime_error( "argument for command, form or function not defined and no filter for processing specified");

		const void* elem;
		int taglevel = 0;
		std::size_t elemsize;
		FilterBase::ElementType etype;

		while (taglevel >= 0)
		{
			if (!flt.inputfilter().get()->getNext( etype, elem, elemsize))
			{
				if (flt.inputfilter()->state() == InputFilter::Open || flt.inputfilter()->state() == InputFilter::Start)
				{
					throw std::runtime_error( "filter not delivering final close tag");
				}
				processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);
				continue;
			}
			if (etype == FilterBase::OpenTag)
			{
				taglevel++;
			}
			else if (etype == FilterBase::CloseTag)
			{
				taglevel--;
			}
			while (!flt.outputfilter().get()->print( etype, elem, elemsize))
			{
				processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);
			}
			LOG_DATA << "[iostream filter] print " << FilterBase::elementTypeName(etype) << " '" << std::string( (const char*)elem, elemsize) << "'"; 
		}
		while (!flt.outputfilter().get()->close())
		{
			processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);
		}
		checkUnconsumedInput( is);
		writeOutput( os, *flt.outputfilter());
		if (taglevel != -1) throw std::runtime_error( "tags not balanced");
		return;
	}
	{
		if (proc[ proc.size()-1] == '~' || provider->hasCommand( proc))
		{
			LOG_TRACE << "Start executing command '" << proc << "'";

			cmdbind::ProtocolHandlerR protocolhnd;
			if (protocol.empty())
			{
				protocolhnd.reset( new cmdbind::ContentOnlyProtocolHandler());
			}
			else
			{
				protocolhnd.reset( provider->protocolHandler( protocol));
				if (!protocolhnd.get()) throw std::runtime_error( std::string("protocol '") + protocol + "' is not defined");
			}
			protocolhnd->setExecContext( execContext);
			if (proc[ proc.size()-1] == '~')
			{
				protocolhnd->setArgumentString( std::string( proc.c_str(), proc.size()-1));
			}
			else
			{
				protocolhnd->setArgumentString( proc + "!");
			}
			protocolhnd->setOutputBuffer( buf.outbuf, buf.outsize, 0);

			std::string lasterr;
			if (!processProtocolHandler( buf, protocolhnd.get(), is, os, lasterr))
			{
				throw std::runtime_error( lasterr);
			}
			// Check if there is unconsumed input left (must not happen):
			checkUnconsumedInput( is);
			return;
		}
	}
	{
		const FormFunction* func = provider->formFunction( proc);
		if (func)
		{
			LOG_TRACE << "Start executing form function '" << proc << "'";

			// ... command is the name of a form function we call directly
			//	with the filter specified:
			Filter flt = getFilter( provider, ifl, ofl);
			if (!flt.inputfilter().get()) throw std::runtime_error( "input filter not found");
			if (!flt.outputfilter().get()) throw std::runtime_error( "output filter not found");
			flt.outputfilter()->setOutputChunkSize( buf.outsize);

			flt.inputfilter()->setValue( "empty", "false");
			TypedInputFilterR inp( new TypingInputFilter( flt.inputfilter()));
			TypedOutputFilterR outp( new TypingOutputFilter( flt.outputfilter()));
			FormFunctionClosureR closure( func->createClosure());
			closure->init( execContext, inp, serialize::Flags::ValidateAttributes);

			while (!closure->call()) processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);

			RedirectFilterClosure res( closure->result(), outp, true);
			while (!res.call()) processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);
			while (!flt.outputfilter()->close()) processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);

			writeOutput( os, *flt.outputfilter());
			checkUnconsumedInput( is);
			return;
		}
	}
	{
		const types::FormDescription* st = provider->formDescription( proc);
		if (st)
		{
			LOG_TRACE << "Start mapping through form '" << proc << "'";

			// ... command is the name a form description -> we simply map
			//	the input with the input/output filters specified 
			//	through the form:
			Filter flt = getFilter( provider, ifl, ofl);
			if (!flt.inputfilter().get()) throw std::runtime_error( "input filter not found");
			if (!flt.outputfilter().get()) throw std::runtime_error( "output filter not found");
			flt.outputfilter()->setOutputChunkSize( buf.outsize);

			types::Form df( st);
			flt.inputfilter()->setValue( "empty", "false");
			TypedInputFilterR inp( new TypingInputFilter( flt.inputfilter()));
			TypedOutputFilterR outp( new TypingOutputFilter( flt.outputfilter()));
			serialize::DDLStructParser closure( &df);
			closure.init( inp, serialize::Flags::ValidateAttributes);

			while (!closure.call()) processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);

			serialize::DDLStructSerializer res( &df);
			res.init( outp, serialize::Flags::None);

			while (!res.call()) processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);
			while (!flt.outputfilter()->close()) processIO( buf, flt.inputfilter().get(), flt.outputfilter().get(), is, os);

			writeOutput( os, *flt.outputfilter());
			checkUnconsumedInput( is);
			return;
		}
	}
	throw std::runtime_error( std::string("identifier '") + proc + "' not defined as command, form or function");
}