docs: private FunctionMember getFunctionMember(Data data, final ExprString name, boolean checkLibrary) throws TemplateException {
  
  	// get Function Library
  	checkLibrary = checkLibrary && data.flibs != null;
  	FunctionLibFunction flf = null;
  	if (checkLibrary) {
  	    if (!(name instanceof Literal)) throw new TemplateException(data.srcCode, "syntax error"); // should never happen!
  
  	    for (int i = 0; i < data.flibs.length; i++) {
  		flf = data.flibs[i].getFunction(((Literal) name).getString());
  		if (flf != null) break;
  	    }
  	    if (flf == null) {
  		checkLibrary = false;
  	    }
  	}
  
  	FunctionMember fm = null;
  	while (true) {
  	    int pos = data.srcCode.getPos();
  	    // Element Function
  	    if (checkLibrary) {
  		BIF bif = new BIF(data.factory, data.settings, flf);
  		// TODO data.ep.add(flf, bif, data.srcCode);
  
  		bif.setArgType(flf.getArgType());
  		try {
  		    bif.setClassDefinition(flf.getFunctionClassDefinition());
  		}
  		catch (Throwable t) {
  		    ExceptionUtil.rethrowIfNecessary(t);
  		    throw new PageRuntimeException(t);
  		}
  		bif.setReturnType(flf.getReturnTypeAsString());
  		fm = bif;
  
  		if (flf.getArgType() == FunctionLibFunction.ARG_DYNAMIC && flf.hasDefaultValues()) {
  		    ArrayList<FunctionLibFunctionArg> args = flf.getArg();
  		    Iterator<FunctionLibFunctionArg> it = args.iterator();
  		    FunctionLibFunctionArg arg;
  		    while (it.hasNext()) {
  			arg = it.next();
  			if (arg.getDefaultValue() != null) bif.addArgument(
  				new NamedArgument(data.factory.createLitString(arg.getName()), data.factory.createLitString(arg.getDefaultValue()), arg.getTypeAsString(), false));
  		    }
  		}
  	    }
  	    else {
  		fm = new UDF(name);
  	    }
  
  	    int count = getFunctionMemberAttrs(data, name, checkLibrary, fm, flf);
  
  	    if (checkLibrary) {
  		// pre
  		if (flf.hasTteClass()) {
  		    FunctionLibFunction tmp = flf.getEvaluator().pre((BIF) fm, flf);
  		    if (tmp != null && tmp != flf) {
  			flf = tmp;
  			data.srcCode.setPos(pos);
  			continue;
  		    }
  		}
  
  		// check max attributes
  		{
  		    boolean isDynamic = flf.getArgType() == FunctionLibFunction.ARG_DYNAMIC;
  		    int max = flf.getArgMax();
  		    // Dynamic
  		    if (isDynamic) {
  			if (max != -1 && max < fm.getArguments().length) throw new TemplateException(data.srcCode,
  				"too many Attributes (" + max + ":" + fm.getArguments().length + ") in function [ " + ASMUtil.display(name) + " ]");
  		    }
  		    // Fix
  		    else {
  			if (flf.getArg().size() < fm.getArguments().length) {
  			    TemplateException te = new TemplateException(data.srcCode,
  				    "too many Attributes (" + flf.getArg().size() + ":" + fm.getArguments().length + ") in function call [" + ASMUtil.display(name) + "]");
  			    UDFUtil.addFunctionDoc(te, flf);
  			    throw te;
  			}
  		    }
  
  		}
  
  		// check min attributes
  		if (flf.getArgMin() > count) {
  		    TemplateException te = new TemplateException(data.srcCode, "too few attributes in function [" + ASMUtil.display(name) + "]");
  		    if (flf.getArgType() == FunctionLibFunction.ARG_FIX) UDFUtil.addFunctionDoc(te, flf);
  		    throw te;
  		}
  
  		// evaluator
  		if (flf.hasTteClass()) {
  		    flf.getEvaluator().execute((BIF) fm, flf);
  
  		}
  	    }
  	    comments(data);
  
  	    if (checkLibrary) data.ep.add(flf, (BIF) fm, data.srcCode);
  
  	    break;
  	}
  
  	return fm;
      }