/** Translates an object of this type to its unboxed representation. */ public void translateUnBox(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); il.append(new CHECKCAST(cpg.addClass(INTEGER_CLASS))); final int index = cpg.addMethodref(INTEGER_CLASS, INT_VALUE, INT_VALUE_SIG); il.append(new INVOKEVIRTUAL(index)); }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); _right.translate(classGen, methodGen); il.append(new CHECKCAST(cpg.addClass(_className))); }
public void translateDesynthesized(ClassGenerator classGen, MethodGenerator methodGen) { final Type tleft = _left.getType(); final InstructionList il = methodGen.getInstructionList(); if (tleft instanceof BooleanType) { _left.translate(classGen, methodGen); _right.translate(classGen, methodGen); _falseList.add( il.append( _op == Operators.EQ ? (BranchInstruction) new IF_ICMPNE(null) : (BranchInstruction) new IF_ICMPEQ(null))); } else if (tleft instanceof NumberType) { _left.translate(classGen, methodGen); _right.translate(classGen, methodGen); if (tleft instanceof RealType) { il.append(DCMPG); _falseList.add( il.append( _op == Operators.EQ ? (BranchInstruction) new IFNE(null) : (BranchInstruction) new IFEQ(null))); } else { _falseList.add( il.append( _op == Operators.EQ ? (BranchInstruction) new IF_ICMPNE(null) : (BranchInstruction) new IF_ICMPEQ(null))); } } else { translate(classGen, methodGen); desynthesize(classGen, methodGen); } }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); // Get two copies of the argument on the stack argument().translate(classGen, methodGen); il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS, "roundF", "(D)D"))); }
/** * Expects an integer on the stack and pushes a boxed integer. Boxed integers are represented by * an instance of <code>java.lang.Integer</code>. * * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */ public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, ReferenceType type) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); il.append(new NEW(cpg.addClass(INTEGER_CLASS))); il.append(DUP_X1); il.append(SWAP); il.append(new INVOKESPECIAL(cpg.addMethodref(INTEGER_CLASS, "<init>", "(I)V"))); }
/** * Translates an integer into the Java type denoted by <code>clazz</code>. Expects an integer on * the stack and pushes a number of the appropriate type after coercion. */ public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, Class clazz) { final InstructionList il = methodGen.getInstructionList(); if (clazz == Character.TYPE) { il.append(I2C); } else if (clazz == Byte.TYPE) { il.append(I2B); } else if (clazz == Short.TYPE) { il.append(I2S); } else if (clazz == Integer.TYPE) { il.append(NOP); } else if (clazz == Long.TYPE) { il.append(I2L); } else if (clazz == Float.TYPE) { il.append(I2F); } else if (clazz == Double.TYPE) { il.append(I2D); } // Is Double <: clazz? I.e. clazz in { Double, Number, Object } else if (clazz.isAssignableFrom(java.lang.Double.class)) { il.append(I2D); Type.Real.translateTo(classGen, methodGen, Type.Reference); } else { ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, toString(), clazz.getName()); classGen.getParser().reportError(Constants.FATAL, err); } }
/** Peephole optimization: Remove sequences of [ALOAD, POP]. */ private void peepHoleOptimization(MethodGenerator methodGen) { final String pattern = "`aload'`pop'`instruction'"; final InstructionList il = methodGen.getInstructionList(); final InstructionFinder find = new InstructionFinder(il); for (Iterator iter = find.search(pattern); iter.hasNext(); ) { InstructionHandle[] match = (InstructionHandle[]) iter.next(); try { il.delete(match[0], match[1]); } catch (TargetLostException e) { // TODO: move target down into the list } } }
/** * Compile a buildKeys() method into the output class. Note that keys for the input document are * created in topLevel(), not in this method. However, we still need this method to create keys * for documents loaded via the XPath document() function. */ private String compileBuildKeys(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = { Util.getJCRefType(DOM_INTF_SIG), Util.getJCRefType(NODE_ITERATOR_SIG), Util.getJCRefType(TRANSLET_OUTPUT_SIG), com.sun.org.apache.bcel.internal.generic.Type.INT }; final String[] argNames = {DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME, "current"}; final InstructionList il = new InstructionList(); final MethodGenerator buildKeys = new MethodGenerator( ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, argTypes, argNames, "buildKeys", _className, il, classGen.getConstantPool()); buildKeys.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); final Enumeration elements = elements(); while (elements.hasMoreElements()) { // xsl:key final Object element = elements.nextElement(); if (element instanceof Key) { final Key key = (Key) element; key.translate(classGen, buildKeys); _keys.put(key.getName(), key); } } il.append(RETURN); // Compute max locals + stack and add method to class buildKeys.stripAttributes(true); buildKeys.setMaxLocals(); buildKeys.setMaxStack(); buildKeys.removeNOPs(); classGen.addMethod(buildKeys.getMethod()); return ("(" + DOM_INTF_SIG + NODE_ITERATOR_SIG + TRANSLET_OUTPUT_SIG + "I)V"); }
/* */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) /* */ { /* 88 */ ConstantPoolGen cpg = classGen.getConstantPool(); /* 89 */ InstructionList il = methodGen.getInstructionList(); /* 90 */ SymbolTable symbolTable = getParser().getSymbolTable(); /* */ /* 93 */ for (int i = 0; i < this._sets.size(); i++) /* */ { /* 95 */ QName name = (QName) this._sets.elementAt(i); /* */ /* 97 */ AttributeSet attrs = symbolTable.lookupAttributeSet(name); /* */ /* 99 */ if (attrs != null) { /* 100 */ String methodName = attrs.getMethodName(); /* 101 */ il.append(classGen.loadTranslet()); /* 102 */ il.append(methodGen.loadDOM()); /* 103 */ il.append(methodGen.loadIterator()); /* 104 */ il.append(methodGen.loadHandler()); /* 105 */ il.append(methodGen.loadCurrentNode()); /* 106 */ int method = cpg.addMethodref( classGen.getClassName(), methodName, "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;I)V"); /* */ /* 108 */ il.append(new INVOKESPECIAL(method)); /* */ } /* */ else /* */ { /* 112 */ Parser parser = getParser(); /* 113 */ String atrs = name.toString(); /* 114 */ reportError(this, parser, "ATTRIBSET_UNDEF_ERR", atrs); /* */ } /* */ } /* */ }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { if (elementCount() == 1) { final Expression exp = (Expression) elementAt(0); exp.translate(classGen, methodGen); } else { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); final int initBuffer = cpg.addMethodref(STRING_BUFFER_CLASS, "<init>", "()V"); final Instruction append = new INVOKEVIRTUAL( cpg.addMethodref( STRING_BUFFER_CLASS, "append", "(" + STRING_SIG + ")" + STRING_BUFFER_SIG)); final int toString = cpg.addMethodref(STRING_BUFFER_CLASS, "toString", "()" + STRING_SIG); il.append(new NEW(cpg.addClass(STRING_BUFFER_CLASS))); il.append(DUP); il.append(new INVOKESPECIAL(initBuffer)); // StringBuffer is on the stack final Iterator<SyntaxTreeNode> elements = elements(); while (elements.hasNext()) { final Expression exp = (Expression) elements.next(); exp.translate(classGen, methodGen); il.append(append); } il.append(new INVOKEVIRTUAL(toString)); } }
/** * Redirect the handles from oldList to newList. "This" flow list is assumed to be relative to * oldList. */ public FlowList copyAndRedirect(InstructionList oldList, InstructionList newList) { final FlowList result = new FlowList(); if (_elements == null) { return result; } final int n = _elements.size(); final Iterator oldIter = oldList.iterator(); final Iterator newIter = newList.iterator(); while (oldIter.hasNext()) { final InstructionHandle oldIh = (InstructionHandle) oldIter.next(); final InstructionHandle newIh = (InstructionHandle) newIter.next(); for (int i = 0; i < n; i++) { if (_elements.elementAt(i) == oldIh) { result.add(newIh); } } } return result; }
/** * Expects an integer on the stack and pushes a 0 if its value is 0 and a 1 otherwise. * * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */ public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type) { final InstructionList il = methodGen.getInstructionList(); final BranchHandle falsec = il.append(new IFEQ(null)); il.append(ICONST_1); final BranchHandle truec = il.append(new GOTO(null)); falsec.setTarget(il.append(ICONST_0)); truec.setTarget(il.append(NOP)); }
/** * Compile transform() into the output class. This method is used to initialize global variables * and global parameters. The current node is set to be the document's root node. */ private void compileTransform(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); /* * Define the the method transform with the following signature: * void transform(DOM, NodeIterator, HandlerBase) */ final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = new com.sun.org.apache.bcel.internal.generic.Type[3]; argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); final String[] argNames = new String[3]; argNames[0] = DOCUMENT_PNAME; argNames[1] = ITERATOR_PNAME; argNames[2] = TRANSLET_OUTPUT_PNAME; final InstructionList il = new InstructionList(); final MethodGenerator transf = new MethodGenerator( ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, argTypes, argNames, "transform", _className, il, classGen.getConstantPool()); transf.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); // Define and initialize current with the root node final LocalVariableGen current = transf.addLocalVariable( "current", com.sun.org.apache.bcel.internal.generic.Type.INT, null, null); final String applyTemplatesSig = classGen.getApplyTemplatesSig(); final int applyTemplates = cpg.addMethodref(getClassName(), "applyTemplates", applyTemplatesSig); final int domField = cpg.addFieldref(getClassName(), DOM_FIELD, DOM_INTF_SIG); // push translet for PUTFIELD il.append(classGen.loadTranslet()); // prepare appropriate DOM implementation if (isMultiDocument()) { il.append(new NEW(cpg.addClass(MULTI_DOM_CLASS))); il.append(DUP); } il.append(classGen.loadTranslet()); il.append(transf.loadDOM()); il.append( new INVOKEVIRTUAL( cpg.addMethodref( TRANSLET_CLASS, "makeDOMAdapter", "(" + DOM_INTF_SIG + ")" + DOM_ADAPTER_SIG))); // DOMAdapter is on the stack if (isMultiDocument()) { final int init = cpg.addMethodref(MULTI_DOM_CLASS, "<init>", "(" + DOM_INTF_SIG + ")V"); il.append(new INVOKESPECIAL(init)); // MultiDOM is on the stack } // store to _dom variable il.append(new PUTFIELD(domField)); // continue with globals initialization final int gitr = cpg.addInterfaceMethodref(DOM_INTF, "getIterator", "()" + NODE_ITERATOR_SIG); il.append(transf.loadDOM()); il.append(new INVOKEINTERFACE(gitr, 1)); il.append(transf.nextNode()); current.setStart(il.append(new ISTORE(current.getIndex()))); // Transfer the output settings to the output post-processor il.append(classGen.loadTranslet()); il.append(transf.loadHandler()); final int index = cpg.addMethodref(TRANSLET_CLASS, "transferOutputSettings", "(" + OUTPUT_HANDLER_SIG + ")V"); il.append(new INVOKEVIRTUAL(index)); /* * Compile buildKeys() method. Note that this method is not * invoked here as keys for the input document are now created * in topLevel(). However, this method is still needed by the * LoadDocument class. */ final String keySig = compileBuildKeys(classGen); final int keyIdx = cpg.addMethodref(getClassName(), "buildKeys", keySig); // Look for top-level elements that need handling final Enumeration toplevel = elements(); if (_globals.size() > 0 || toplevel.hasMoreElements()) { // Compile method for handling top-level elements final String topLevelSig = compileTopLevel(classGen); // Get a reference to that method final int topLevelIdx = cpg.addMethodref(getClassName(), "topLevel", topLevelSig); // Push all parameters on the stack and call topLevel() il.append(classGen.loadTranslet()); // The 'this' pointer il.append(classGen.loadTranslet()); il.append(new GETFIELD(domField)); // The DOM reference il.append(transf.loadIterator()); il.append(transf.loadHandler()); // The output handler il.append(new INVOKEVIRTUAL(topLevelIdx)); } // start document il.append(transf.loadHandler()); il.append(transf.startDocument()); // push first arg for applyTemplates il.append(classGen.loadTranslet()); // push translet for GETFIELD to get DOM arg il.append(classGen.loadTranslet()); il.append(new GETFIELD(domField)); // push remaining 2 args il.append(transf.loadIterator()); il.append(transf.loadHandler()); il.append(new INVOKEVIRTUAL(applyTemplates)); // endDocument il.append(transf.loadHandler()); il.append(transf.endDocument()); il.append(RETURN); // Compute max locals + stack and add method to class classGen.addMethod(transf); }
/** * This method is called when the constructor is compiled in Stylesheet.compileConstructor() and * not as the syntax tree is traversed. */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { ConstantPoolGen cpg = classGen.getConstantPool(); InstructionList il = methodGen.getInstructionList(); // DecimalFormatSymbols.<init>(Locale); // xsl:decimal-format - except for the NaN and infinity attributes. final int init = cpg.addMethodref(DFS_CLASS, "<init>", "(" + LOCALE_SIG + ")V"); // Push the format name on the stack for call to addDecimalFormat() il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, _name.toString())); // Manufacture a DecimalFormatSymbols on the stack // for call to addDecimalFormat() // Use the US Locale as the default, as most of its settings // are equivalent to the default settings required of il.append(new NEW(cpg.addClass(DFS_CLASS))); il.append(DUP); il.append(new GETSTATIC(cpg.addFieldref(LOCALE_CLASS, "US", LOCALE_SIG))); il.append(new INVOKESPECIAL(init)); String tmp = getAttribute("NaN"); if ((tmp == null) || (tmp.equals(EMPTYSTRING))) { int nan = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "NaN")); il.append(new INVOKEVIRTUAL(nan)); } tmp = getAttribute("infinity"); if ((tmp == null) || (tmp.equals(EMPTYSTRING))) { int inf = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "Infinity")); il.append(new INVOKEVIRTUAL(inf)); } final int nAttributes = _attributes.getLength(); for (int i = 0; i < nAttributes; i++) { final String name = _attributes.getQName(i); final String value = _attributes.getValue(i); boolean valid = true; int method = 0; if (name.equals("decimal-separator")) { // DecimalFormatSymbols.setDecimalSeparator(); method = cpg.addMethodref(DFS_CLASS, "setDecimalSeparator", "(C)V"); } else if (name.equals("grouping-separator")) { method = cpg.addMethodref(DFS_CLASS, "setGroupingSeparator", "(C)V"); } else if (name.equals("minus-sign")) { method = cpg.addMethodref(DFS_CLASS, "setMinusSign", "(C)V"); } else if (name.equals("percent")) { method = cpg.addMethodref(DFS_CLASS, "setPercent", "(C)V"); } else if (name.equals("per-mille")) { method = cpg.addMethodref(DFS_CLASS, "setPerMill", "(C)V"); } else if (name.equals("zero-digit")) { method = cpg.addMethodref(DFS_CLASS, "setZeroDigit", "(C)V"); } else if (name.equals("digit")) { method = cpg.addMethodref(DFS_CLASS, "setDigit", "(C)V"); } else if (name.equals("pattern-separator")) { method = cpg.addMethodref(DFS_CLASS, "setPatternSeparator", "(C)V"); } else if (name.equals("NaN")) { method = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, value)); il.append(new INVOKEVIRTUAL(method)); valid = false; } else if (name.equals("infinity")) { method = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, value)); il.append(new INVOKEVIRTUAL(method)); valid = false; } else { valid = false; } if (valid) { il.append(DUP); il.append(new PUSH(cpg, value.charAt(0))); il.append(new INVOKEVIRTUAL(method)); } } final int put = cpg.addMethodref(TRANSLET_CLASS, "addDecimalFormat", "(" + STRING_SIG + DFS_SIG + ")V"); il.append(new INVOKEVIRTUAL(put)); }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); if (!_isLiteral) { // if the ncname is an AVT, then the ncname has to be checked at runtime if it is a valid // ncname LocalVariableGen nameValue = methodGen.addLocalVariable2("nameValue", Util.getJCRefType(STRING_SIG), null); // store the name into a variable first so _name.translate only needs to be called once _name.translate(classGen, methodGen); nameValue.setStart(il.append(new ASTORE(nameValue.getIndex()))); il.append(new ALOAD(nameValue.getIndex())); // call checkNCName if the name is an AVT final int check = cpg.addMethodref(BASIS_LIBRARY_CLASS, "checkNCName", "(" + STRING_SIG + ")V"); il.append(new INVOKESTATIC(check)); // Save the current handler base on the stack il.append(methodGen.loadHandler()); il.append(DUP); // first arg to "attributes" call // load name value again nameValue.setEnd(il.append(new ALOAD(nameValue.getIndex()))); } else { // Save the current handler base on the stack il.append(methodGen.loadHandler()); il.append(DUP); // first arg to "attributes" call // Push attribute name _name.translate(classGen, methodGen); // 2nd arg } il.append(classGen.loadTranslet()); il.append( new GETFIELD( cpg.addFieldref(TRANSLET_CLASS, "stringValueHandler", STRING_VALUE_HANDLER_SIG))); il.append(DUP); il.append(methodGen.storeHandler()); // translate contents with substituted handler translateContents(classGen, methodGen); // get String out of the handler il.append( new INVOKEVIRTUAL( cpg.addMethodref(STRING_VALUE_HANDLER, "getValueOfPI", "()" + STRING_SIG))); // call "processingInstruction" final int processingInstruction = cpg.addInterfaceMethodref( TRANSLET_OUTPUT_INTERFACE, "processingInstruction", "(" + STRING_SIG + STRING_SIG + ")V"); il.append(new INVOKEINTERFACE(processingInstruction, 3)); // Restore old handler base from stack il.append(methodGen.storeHandler()); }
/** * Expects an integer on the stack and pushes its string value by calling <code> * Integer.toString(int i)</code>. * * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */ public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, StringType type) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); il.append(new INVOKESTATIC(cpg.addMethodref(INTEGER_CLASS, "toString", "(I)" + STRING_SIG))); }
/** Compile the translet's constructor */ private void compileConstructor(ClassGenerator classGen, Output output) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = new InstructionList(); final MethodGenerator constructor = new MethodGenerator( ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, null, null, "<init>", _className, il, cpg); // Call the constructor in the AbstractTranslet superclass il.append(classGen.loadTranslet()); il.append(new INVOKESPECIAL(cpg.addMethodref(TRANSLET_CLASS, "<init>", "()V"))); constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append( new GETSTATIC(cpg.addFieldref(_className, STATIC_NAMES_ARRAY_FIELD, NAMES_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, NAMES_INDEX, NAMES_INDEX_SIG))); il.append(classGen.loadTranslet()); il.append(new GETSTATIC(cpg.addFieldref(_className, STATIC_URIS_ARRAY_FIELD, URIS_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, URIS_INDEX, URIS_INDEX_SIG))); constructor.markChunkEnd(); constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append( new GETSTATIC(cpg.addFieldref(_className, STATIC_TYPES_ARRAY_FIELD, TYPES_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, TYPES_INDEX, TYPES_INDEX_SIG))); constructor.markChunkEnd(); constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append( new GETSTATIC( cpg.addFieldref(_className, STATIC_NAMESPACE_ARRAY_FIELD, NAMESPACE_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, NAMESPACE_INDEX, NAMESPACE_INDEX_SIG))); constructor.markChunkEnd(); constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, AbstractTranslet.CURRENT_TRANSLET_VERSION)); il.append( new PUTFIELD( cpg.addFieldref(TRANSLET_CLASS, TRANSLET_VERSION_INDEX, TRANSLET_VERSION_INDEX_SIG))); constructor.markChunkEnd(); if (_hasIdCall) { constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, Boolean.TRUE)); il.append( new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, HASIDCALL_INDEX, HASIDCALL_INDEX_SIG))); constructor.markChunkEnd(); } // Compile in code to set the output configuration from <xsl:output> if (output != null) { // Set all the output settings files in the translet constructor.markChunkStart(); output.translate(classGen, constructor); constructor.markChunkEnd(); } // Compile default decimal formatting symbols. // This is an implicit, nameless xsl:decimal-format top-level element. if (_numberFormattingUsed) { constructor.markChunkStart(); DecimalFormatting.translateDefaultDFS(classGen, constructor); constructor.markChunkEnd(); } il.append(RETURN); classGen.addMethod(constructor); }
/** * Creates the default, nameless, DecimalFormat object in AbstractTranslet's format_symbols * hashtable. This should be called for every stylesheet, and the entry may be overridden by later * nameless xsl:decimal-format instructions. */ public static void translateDefaultDFS(ClassGenerator classGen, MethodGenerator methodGen) { ConstantPoolGen cpg = classGen.getConstantPool(); InstructionList il = methodGen.getInstructionList(); final int init = cpg.addMethodref(DFS_CLASS, "<init>", "(" + LOCALE_SIG + ")V"); // Push the format name, which is empty, on the stack // for call to addDecimalFormat() il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, EMPTYSTRING)); // Manufacture a DecimalFormatSymbols on the stack for // call to addDecimalFormat(). Use the US Locale as the // default, as most of its settings are equivalent to // the default settings required of xsl:decimal-format - // except for the NaN and infinity attributes. il.append(new NEW(cpg.addClass(DFS_CLASS))); il.append(DUP); il.append(new GETSTATIC(cpg.addFieldref(LOCALE_CLASS, "US", LOCALE_SIG))); il.append(new INVOKESPECIAL(init)); int nan = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "NaN")); il.append(new INVOKEVIRTUAL(nan)); int inf = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "Infinity")); il.append(new INVOKEVIRTUAL(inf)); final int put = cpg.addMethodref(TRANSLET_CLASS, "addDecimalFormat", "(" + STRING_SIG + DFS_SIG + ")V"); il.append(new INVOKEVIRTUAL(put)); }
/** * Expects an integer on the stack and translates it to a non-synthesized boolean. It does not * push a 0 or a 1 but instead returns branchhandle list to be appended to the false list. * * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized */ public FlowList translateToDesynthesized( ClassGenerator classGen, MethodGenerator methodGen, BooleanType type) { final InstructionList il = methodGen.getInstructionList(); return new FlowList(il.append(new IFEQ(null))); }
/** * Compile the namesArray, urisArray and typesArray into the static initializer. They are * read-only from the translet. All translet instances can share a single copy of this informtion. */ private void compileStaticInitializer(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = new InstructionList(); final MethodGenerator staticConst = new MethodGenerator( ACC_PUBLIC | ACC_STATIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, null, null, "<clinit>", _className, il, cpg); addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMES_ARRAY_FIELD); addStaticField(classGen, "[" + STRING_SIG, STATIC_URIS_ARRAY_FIELD); addStaticField(classGen, "[I", STATIC_TYPES_ARRAY_FIELD); addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMESPACE_ARRAY_FIELD); // Create fields of type char[] that will contain literal text from // the stylesheet. final int charDataFieldCount = getXSLTC().getCharacterDataCount(); for (int i = 0; i < charDataFieldCount; i++) { addStaticField(classGen, STATIC_CHAR_DATA_FIELD_SIG, STATIC_CHAR_DATA_FIELD + i); } // Put the names array into the translet - used for dom/translet mapping final Vector namesIndex = getXSLTC().getNamesIndex(); int size = namesIndex.size(); String[] namesArray = new String[size]; String[] urisArray = new String[size]; int[] typesArray = new int[size]; int index; for (int i = 0; i < size; i++) { String encodedName = (String) namesIndex.elementAt(i); if ((index = encodedName.lastIndexOf(':')) > -1) { urisArray[i] = encodedName.substring(0, index); } index = index + 1; if (encodedName.charAt(index) == '@') { typesArray[i] = DTM.ATTRIBUTE_NODE; index++; } else if (encodedName.charAt(index) == '?') { typesArray[i] = DTM.NAMESPACE_NODE; index++; } else { typesArray[i] = DTM.ELEMENT_NODE; } if (index == 0) { namesArray[i] = encodedName; } else { namesArray[i] = encodedName.substring(index); } } staticConst.markChunkStart(); il.append(new PUSH(cpg, size)); il.append(new ANEWARRAY(cpg.addClass(STRING))); int namesArrayRef = cpg.addFieldref(_className, STATIC_NAMES_ARRAY_FIELD, NAMES_INDEX_SIG); il.append(new PUTSTATIC(namesArrayRef)); staticConst.markChunkEnd(); for (int i = 0; i < size; i++) { final String name = namesArray[i]; staticConst.markChunkStart(); il.append(new GETSTATIC(namesArrayRef)); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, name)); il.append(AASTORE); staticConst.markChunkEnd(); } staticConst.markChunkStart(); il.append(new PUSH(cpg, size)); il.append(new ANEWARRAY(cpg.addClass(STRING))); int urisArrayRef = cpg.addFieldref(_className, STATIC_URIS_ARRAY_FIELD, URIS_INDEX_SIG); il.append(new PUTSTATIC(urisArrayRef)); staticConst.markChunkEnd(); for (int i = 0; i < size; i++) { final String uri = urisArray[i]; staticConst.markChunkStart(); il.append(new GETSTATIC(urisArrayRef)); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, uri)); il.append(AASTORE); staticConst.markChunkEnd(); } staticConst.markChunkStart(); il.append(new PUSH(cpg, size)); il.append(new NEWARRAY(BasicType.INT)); int typesArrayRef = cpg.addFieldref(_className, STATIC_TYPES_ARRAY_FIELD, TYPES_INDEX_SIG); il.append(new PUTSTATIC(typesArrayRef)); staticConst.markChunkEnd(); for (int i = 0; i < size; i++) { final int nodeType = typesArray[i]; staticConst.markChunkStart(); il.append(new GETSTATIC(typesArrayRef)); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, nodeType)); il.append(IASTORE); } // Put the namespace names array into the translet final Vector namespaces = getXSLTC().getNamespaceIndex(); staticConst.markChunkStart(); il.append(new PUSH(cpg, namespaces.size())); il.append(new ANEWARRAY(cpg.addClass(STRING))); int namespaceArrayRef = cpg.addFieldref(_className, STATIC_NAMESPACE_ARRAY_FIELD, NAMESPACE_INDEX_SIG); il.append(new PUTSTATIC(namespaceArrayRef)); staticConst.markChunkEnd(); for (int i = 0; i < namespaces.size(); i++) { final String ns = (String) namespaces.elementAt(i); staticConst.markChunkStart(); il.append(new GETSTATIC(namespaceArrayRef)); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, ns)); il.append(AASTORE); staticConst.markChunkEnd(); } // Grab all the literal text in the stylesheet and put it in a char[] final int charDataCount = getXSLTC().getCharacterDataCount(); final int toCharArray = cpg.addMethodref(STRING, "toCharArray", "()[C"); for (int i = 0; i < charDataCount; i++) { staticConst.markChunkStart(); il.append(new PUSH(cpg, getXSLTC().getCharacterData(i))); il.append(new INVOKEVIRTUAL(toCharArray)); il.append( new PUTSTATIC( cpg.addFieldref(_className, STATIC_CHAR_DATA_FIELD + i, STATIC_CHAR_DATA_FIELD_SIG))); staticConst.markChunkEnd(); } il.append(RETURN); classGen.addMethod(staticConst); }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); final Type tleft = _left.getType(); Type tright = _right.getType(); if (tleft instanceof BooleanType || tleft instanceof NumberType) { translateDesynthesized(classGen, methodGen); synthesize(classGen, methodGen); return; } if (tleft instanceof StringType) { final int equals = cpg.addMethodref(STRING_CLASS, "equals", "(" + OBJECT_SIG + ")Z"); _left.translate(classGen, methodGen); _right.translate(classGen, methodGen); il.append(new INVOKEVIRTUAL(equals)); if (_op == Operators.NE) { il.append(ICONST_1); il.append(IXOR); // not x <-> x xor 1 } return; } BranchHandle truec, falsec; if (tleft instanceof ResultTreeType) { if (tright instanceof BooleanType) { _right.translate(classGen, methodGen); if (_op == Operators.NE) { il.append(ICONST_1); il.append(IXOR); // not x <-> x xor 1 } return; } if (tright instanceof RealType) { _left.translate(classGen, methodGen); tleft.translateTo(classGen, methodGen, Type.Real); _right.translate(classGen, methodGen); il.append(DCMPG); falsec = il.append( _op == Operators.EQ ? (BranchInstruction) new IFNE(null) : (BranchInstruction) new IFEQ(null)); il.append(ICONST_1); truec = il.append(new GOTO(null)); falsec.setTarget(il.append(ICONST_0)); truec.setTarget(il.append(NOP)); return; } // Next, result-tree/string and result-tree/result-tree comparisons _left.translate(classGen, methodGen); tleft.translateTo(classGen, methodGen, Type.String); _right.translate(classGen, methodGen); if (tright instanceof ResultTreeType) { tright.translateTo(classGen, methodGen, Type.String); } final int equals = cpg.addMethodref(STRING_CLASS, "equals", "(" + OBJECT_SIG + ")Z"); il.append(new INVOKEVIRTUAL(equals)); if (_op == Operators.NE) { il.append(ICONST_1); il.append(IXOR); // not x <-> x xor 1 } return; } if (tleft instanceof NodeSetType && tright instanceof BooleanType) { _left.translate(classGen, methodGen); _left.startIterator(classGen, methodGen); Type.NodeSet.translateTo(classGen, methodGen, Type.Boolean); _right.translate(classGen, methodGen); il.append(IXOR); // x != y <-> x xor y if (_op == Operators.EQ) { il.append(ICONST_1); il.append(IXOR); // not x <-> x xor 1 } return; } if (tleft instanceof NodeSetType && tright instanceof StringType) { _left.translate(classGen, methodGen); _left.startIterator(classGen, methodGen); // needed ? _right.translate(classGen, methodGen); il.append(new PUSH(cpg, _op)); il.append(methodGen.loadDOM()); final int cmp = cpg.addMethodref( BASIS_LIBRARY_CLASS, "compare", "(" + tleft.toSignature() + tright.toSignature() + "I" + DOM_INTF_SIG + ")Z"); il.append(new INVOKESTATIC(cmp)); return; } // Next, node-set/t for t in {real, string, node-set, result-tree} _left.translate(classGen, methodGen); _left.startIterator(classGen, methodGen); _right.translate(classGen, methodGen); _right.startIterator(classGen, methodGen); // Cast a result tree to a string to use an existing compare if (tright instanceof ResultTreeType) { tright.translateTo(classGen, methodGen, Type.String); tright = Type.String; } // Call the appropriate compare() from the BasisLibrary il.append(new PUSH(cpg, _op)); il.append(methodGen.loadDOM()); final int compare = cpg.addMethodref( BASIS_LIBRARY_CLASS, "compare", "(" + tleft.toSignature() + tright.toSignature() + "I" + DOM_INTF_SIG + ")Z"); il.append(new INVOKESTATIC(compare)); }
/** * Compile a topLevel() method into the output class. This method is called from transform() to * handle all non-template top-level elements. Returns the signature of the topLevel() method. * * <p>Global variables/params and keys are first sorted to resolve dependencies between them. The * XSLT 1.0 spec does not allow a key to depend on a variable. However, for compatibility with * Xalan interpretive, that type of dependency is allowed. Note also that the buildKeys() method * is still generated as it is used by the LoadDocument class, but it no longer called from * transform(). */ private String compileTopLevel(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = { Util.getJCRefType(DOM_INTF_SIG), Util.getJCRefType(NODE_ITERATOR_SIG), Util.getJCRefType(TRANSLET_OUTPUT_SIG) }; final String[] argNames = {DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME}; final InstructionList il = new InstructionList(); final MethodGenerator toplevel = new MethodGenerator( ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, argTypes, argNames, "topLevel", _className, il, classGen.getConstantPool()); toplevel.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); // Define and initialize 'current' variable with the root node final LocalVariableGen current = toplevel.addLocalVariable( "current", com.sun.org.apache.bcel.internal.generic.Type.INT, null, null); final int setFilter = cpg.addInterfaceMethodref( DOM_INTF, "setFilter", "(Lcom/sun/org/apache/xalan/internal/xsltc/StripFilter;)V"); final int gitr = cpg.addInterfaceMethodref(DOM_INTF, "getIterator", "()" + NODE_ITERATOR_SIG); il.append(toplevel.loadDOM()); il.append(new INVOKEINTERFACE(gitr, 1)); il.append(toplevel.nextNode()); current.setStart(il.append(new ISTORE(current.getIndex()))); // Create a new list containing variables/params + keys Vector varDepElements = new Vector(_globals); Enumeration elements = elements(); while (elements.hasMoreElements()) { final Object element = elements.nextElement(); if (element instanceof Key) { varDepElements.add(element); } } // Determine a partial order for the variables/params and keys varDepElements = resolveDependencies(varDepElements); // Translate vars/params and keys in the right order final int count = varDepElements.size(); for (int i = 0; i < count; i++) { final TopLevelElement tle = (TopLevelElement) varDepElements.elementAt(i); tle.translate(classGen, toplevel); if (tle instanceof Key) { final Key key = (Key) tle; _keys.put(key.getName(), key); } } // Compile code for other top-level elements Vector whitespaceRules = new Vector(); elements = elements(); while (elements.hasMoreElements()) { final Object element = elements.nextElement(); // xsl:decimal-format if (element instanceof DecimalFormatting) { ((DecimalFormatting) element).translate(classGen, toplevel); } // xsl:strip/preserve-space else if (element instanceof Whitespace) { whitespaceRules.addAll(((Whitespace) element).getRules()); } } // Translate all whitespace strip/preserve rules if (whitespaceRules.size() > 0) { Whitespace.translateRules(whitespaceRules, classGen); } if (classGen.containsMethod(STRIP_SPACE, STRIP_SPACE_PARAMS) != null) { il.append(toplevel.loadDOM()); il.append(classGen.loadTranslet()); il.append(new INVOKEINTERFACE(setFilter, 2)); } il.append(RETURN); // Compute max locals + stack and add method to class classGen.addMethod(toplevel); return ("(" + DOM_INTF_SIG + NODE_ITERATOR_SIG + TRANSLET_OUTPUT_SIG + ")V"); }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); // Save current node and current iterator on the stack il.append(methodGen.loadCurrentNode()); il.append(methodGen.loadIterator()); // Collect sort objects associated with this instruction final Vector sortObjects = new Vector(); Enumeration children = elements(); while (children.hasMoreElements()) { final Object child = children.nextElement(); if (child instanceof Sort) { sortObjects.addElement(child); } } if ((_type != null) && (_type instanceof ResultTreeType)) { // Store existing DOM on stack - must be restored when loop is done il.append(methodGen.loadDOM()); // <xsl:sort> cannot be applied to a result tree - issue warning if (sortObjects.size() > 0) { ErrorMsg msg = new ErrorMsg(ErrorMsg.RESULT_TREE_SORT_ERR, this); getParser().reportError(WARNING, msg); } // Put the result tree on the stack (DOM) _select.translate(classGen, methodGen); // Get an iterator for the whole DOM - excluding the root node _type.translateTo(classGen, methodGen, Type.NodeSet); // Store the result tree as the default DOM il.append(SWAP); il.append(methodGen.storeDOM()); } else { // Compile node iterator if (sortObjects.size() > 0) { Sort.translateSortIterator(classGen, methodGen, _select, sortObjects); } else { _select.translate(classGen, methodGen); } if (_type instanceof ReferenceType == false) { il.append(methodGen.loadContextNode()); il.append(methodGen.setStartNode()); } } // Overwrite current iterator il.append(methodGen.storeIterator()); // Give local variables (if any) default values before starting loop initializeVariables(classGen, methodGen); final BranchHandle nextNode = il.append(new GOTO(null)); final InstructionHandle loop = il.append(NOP); translateContents(classGen, methodGen); nextNode.setTarget(il.append(methodGen.loadIterator())); il.append(methodGen.nextNode()); il.append(DUP); il.append(methodGen.storeCurrentNode()); il.append(new IFGT(loop)); // Restore current DOM (if result tree was used instead for this loop) if ((_type != null) && (_type instanceof ResultTreeType)) { il.append(methodGen.storeDOM()); } // Restore current node and current iterator from the stack il.append(methodGen.storeIterator()); il.append(methodGen.storeCurrentNode()); }