📄 functioncall.java
字号:
} } // Invoke the method in the basis library index = cpg.addMethodref(BASIS_LIBRARY_CLASS, name, _chosenMethodType.toSignature(args)); il.append(new INVOKESTATIC(index)); } // Add call to BasisLibrary.unresolved_externalF() to generate // run-time error message for unsupported external functions else if (unresolvedExternal) { index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "unresolved_externalF", "(Ljava/lang/String;)V"); il.append(new PUSH(cpg, _fname.toString())); il.append(new INVOKESTATIC(index)); } else if (_isExtConstructor) { if (isSecureProcessing) translateUnallowedExtension(cpg, il); final String clazz = _chosenConstructor.getDeclaringClass().getName(); Class[] paramTypes = _chosenConstructor.getParameterTypes(); LocalVariableGen[] paramTemp = new LocalVariableGen[n]; // Backwards branches are prohibited if an uninitialized object is // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed. // We don't know whether this code might contain backwards branches // so we mustn't create the new object until after we've created // the suspect arguments to its constructor. Instead we calculate // the values of the arguments to the constructor first, store them // in temporary variables, create the object and reload the // arguments from the temporaries to avoid the problem. for (int i = 0; i < n; i++) { final Expression exp = argument(i); Type expType = exp.getType(); exp.translate(classGen, methodGen); // Convert the argument to its Java type exp.startIterator(classGen, methodGen); expType.translateTo(classGen, methodGen, paramTypes[i]); paramTemp[i] = methodGen.addLocalVariable("function_call_tmp"+i, expType.toJCType(), il.getEnd(), null); il.append(expType.STORE(paramTemp[i].getIndex())); } il.append(new NEW(cpg.addClass(_className))); il.append(InstructionConstants.DUP); for (int i = 0; i < n; i++) { final Expression arg = argument(i); il.append(arg.getType().LOAD(paramTemp[i].getIndex())); } final StringBuffer buffer = new StringBuffer(); buffer.append('('); for (int i = 0; i < paramTypes.length; i++) { buffer.append(getSignature(paramTypes[i])); } buffer.append(')'); buffer.append("V"); index = cpg.addMethodref(clazz, "<init>", buffer.toString()); il.append(new INVOKESPECIAL(index)); // Convert the return type back to our internal type (Type.Object).translateFrom(classGen, methodGen, _chosenConstructor.getDeclaringClass()); } // Invoke function calls that are handled in separate classes else { if (isSecureProcessing) translateUnallowedExtension(cpg, il); final String clazz = _chosenMethod.getDeclaringClass().getName(); Class[] paramTypes = _chosenMethod.getParameterTypes(); // Push "this" if it is an instance method if (_thisArgument != null) { _thisArgument.translate(classGen, methodGen); } for (int i = 0; i < n; i++) { final Expression exp = argument(i); exp.translate(classGen, methodGen); // Convert the argument to its Java type exp.startIterator(classGen, methodGen); exp.getType().translateTo(classGen, methodGen, paramTypes[i]); } final StringBuffer buffer = new StringBuffer(); buffer.append('('); for (int i = 0; i < paramTypes.length; i++) { buffer.append(getSignature(paramTypes[i])); } buffer.append(')'); buffer.append(getSignature(_chosenMethod.getReturnType())); if (_thisArgument != null && _clazz.isInterface()) { index = cpg.addInterfaceMethodref(clazz, _fname.getLocalPart(), buffer.toString()); il.append(new INVOKEINTERFACE(index, n+1)); } else { index = cpg.addMethodref(clazz, _fname.getLocalPart(), buffer.toString()); il.append(_thisArgument != null ? (InvokeInstruction) new INVOKEVIRTUAL(index) : (InvokeInstruction) new INVOKESTATIC(index)); } // Convert the return type back to our internal type _type.translateFrom(classGen, methodGen, _chosenMethod.getReturnType()); } } public String toString() { return "funcall(" + _fname + ", " + _arguments + ')'; } public boolean isStandard() { final String namespace = _fname.getNamespace(); return (namespace == null) || (namespace.equals(Constants.EMPTYSTRING)); } public boolean isExtension() { final String namespace = _fname.getNamespace(); return (namespace != null) && (namespace.equals(EXT_XSLTC)); } /** * Returns a vector with all methods named <code>_fname</code> * after stripping its namespace or <code>null</code> * if no such methods exist. */ private Vector findMethods() { Vector result = null; final String namespace = _fname.getNamespace(); if (_className != null && _className.length() > 0) { final int nArgs = _arguments.size(); try { if (_clazz == null) { _clazz = ObjectFactory.findProviderClass( _className, ObjectFactory.findClassLoader(), true); if (_clazz == null) { final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className); getParser().reportError(Constants.ERROR, msg); } } final String methodName = _fname.getLocalPart(); final Method[] methods = _clazz.getMethods(); for (int i = 0; i < methods.length; i++) { final int mods = methods[i].getModifiers(); // Is it public and same number of args ? if (Modifier.isPublic(mods) && methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == nArgs) { if (result == null) { result = new Vector(); } result.addElement(methods[i]); } } } catch (ClassNotFoundException e) { final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className); getParser().reportError(Constants.ERROR, msg); } } return result; } /** * Returns a vector with all constructors named <code>_fname</code> * after stripping its namespace or <code>null</code> * if no such methods exist. */ private Vector findConstructors() { Vector result = null; final String namespace = _fname.getNamespace(); final int nArgs = _arguments.size(); try { if (_clazz == null) { _clazz = ObjectFactory.findProviderClass( _className, ObjectFactory.findClassLoader(), true); if (_clazz == null) { final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className); getParser().reportError(Constants.ERROR, msg); } } final Constructor[] constructors = _clazz.getConstructors(); for (int i = 0; i < constructors.length; i++) { final int mods = constructors[i].getModifiers(); // Is it public, static and same number of args ? if (Modifier.isPublic(mods) && constructors[i].getParameterTypes().length == nArgs) { if (result == null) { result = new Vector(); } result.addElement(constructors[i]); } } } catch (ClassNotFoundException e) { final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className); getParser().reportError(Constants.ERROR, msg); } return result; } /** * Compute the JVM signature for the class. */ static final String getSignature(Class clazz) { if (clazz.isArray()) { final StringBuffer sb = new StringBuffer(); Class cl = clazz; while (cl.isArray()) { sb.append("["); cl = cl.getComponentType(); } sb.append(getSignature(cl)); return sb.toString(); } else if (clazz.isPrimitive()) { if (clazz == Integer.TYPE) { return "I"; } else if (clazz == Byte.TYPE) { return "B"; } else if (clazz == Long.TYPE) { return "J"; } else if (clazz == Float.TYPE) { return "F"; } else if (clazz == Double.TYPE) { return "D"; } else if (clazz == Short.TYPE) { return "S"; } else if (clazz == Character.TYPE) { return "C"; } else if (clazz == Boolean.TYPE) { return "Z"; } else if (clazz == Void.TYPE) { return "V"; } else { final String name = clazz.toString(); ErrorMsg err = new ErrorMsg(ErrorMsg.UNKNOWN_SIG_TYPE_ERR,name); throw new Error(err.toString()); } } else { return "L" + clazz.getName().replace('.', '/') + ';'; } } /** * Compute the JVM method descriptor for the method. */ static final String getSignature(Method meth) { final StringBuffer sb = new StringBuffer(); sb.append('('); final Class[] params = meth.getParameterTypes(); // avoid clone for (int j = 0; j < params.length; j++) { sb.append(getSignature(params[j])); } return sb.append(')').append(getSignature(meth.getReturnType())) .toString(); } /** * Compute the JVM constructor descriptor for the constructor. */ static final String getSignature(Constructor cons) { final StringBuffer sb = new StringBuffer(); sb.append('('); final Class[] params = cons.getParameterTypes(); // avoid clone for (int j = 0; j < params.length; j++) { sb.append(getSignature(params[j])); } return sb.append(")V").toString(); } /** * Return the signature of the current method */ private String getMethodSignature(Vector argsType) { final StringBuffer buf = new StringBuffer(_className); buf.append('.').append(_fname.getLocalPart()).append('('); int nArgs = argsType.size(); for (int i = 0; i < nArgs; i++) { final Type intType = (Type)argsType.elementAt(i); buf.append(intType.toString()); if (i < nArgs - 1) buf.append(", "); } buf.append(')'); return buf.toString(); } /** * To support EXSLT extensions, convert names with dash to allowable Java names: * e.g., convert abc-xyz to abcXyz. * Note: dashes only appear in middle of an EXSLT function or element name. */ protected static String replaceDash(String name) { char dash = '-'; StringBuffer buff = new StringBuffer(""); for (int i = 0; i < name.length(); i++) { if (i > 0 && name.charAt(i-1) == dash) buff.append(Character.toUpperCase(name.charAt(i))); else if (name.charAt(i) != dash) buff.append(name.charAt(i)); } return buff.toString(); } /** * Translate code to call the BasisLibrary.unallowed_extensionF(String) * method. */ private void translateUnallowedExtension(ConstantPoolGen cpg, InstructionList il) { int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "unallowed_extension_functionF", "(Ljava/lang/String;)V"); il.append(new PUSH(cpg, _fname.toString())); il.append(new INVOKESTATIC(index)); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -