1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xalan.internal.xsltc.compiler; 23 24 import com.sun.org.apache.bcel.internal.generic.BranchHandle; 25 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 26 import com.sun.org.apache.bcel.internal.generic.GOTO; 27 import com.sun.org.apache.bcel.internal.generic.IFEQ; 28 import com.sun.org.apache.bcel.internal.generic.IF_ICMPEQ; 29 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 30 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 31 import com.sun.org.apache.bcel.internal.generic.InstructionHandle; 32 import com.sun.org.apache.bcel.internal.generic.InstructionList; 33 import com.sun.org.apache.bcel.internal.generic.PUSH; 34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 38 import com.sun.org.apache.xml.internal.dtm.Axis; 39 import com.sun.org.apache.xml.internal.dtm.DTM; 40 41 /** 42 * @author Morten Jorgensen 43 */ 44 final class ProcessingInstructionPattern extends StepPattern { 45 46 private String _name = null; 47 private boolean _typeChecked = false; 48 49 /** 50 * Handles calls with no parameter (current node is implicit parameter). 51 */ 52 public ProcessingInstructionPattern(String name) { 53 super(Axis.CHILD, DTM.PROCESSING_INSTRUCTION_NODE, null); 54 _name = name; 55 //if (_name.equals("*")) _typeChecked = true; no wildcard allowed! 56 } 57 58 /** 59 * 60 */ 61 public double getDefaultPriority() { 62 return (_name != null) ? 0.0 : -0.5; 63 } 64 public String toString() { 65 if (_predicates == null) 66 return "processing-instruction("+_name+")"; 67 else 68 return "processing-instruction("+_name+")"+_predicates; 69 } 70 71 public void reduceKernelPattern() { 72 _typeChecked = true; 73 } 74 75 public boolean isWildcard() { 76 return false; 77 } 78 79 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 80 if (hasPredicates()) { 81 // Type check all the predicates (e -> position() = e) 82 final int n = _predicates.size(); 83 for (int i = 0; i < n; i++) { 84 final Predicate pred = (Predicate)_predicates.elementAt(i); 85 pred.typeCheck(stable); 86 } 87 } 88 return Type.NodeSet; 89 } 90 91 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 92 final ConstantPoolGen cpg = classGen.getConstantPool(); 93 final InstructionList il = methodGen.getInstructionList(); 94 95 // context node is on the stack 96 int gname = cpg.addInterfaceMethodref(DOM_INTF, 97 "getNodeName", 98 "(I)Ljava/lang/String;"); 99 int cmp = cpg.addMethodref(STRING_CLASS, 100 "equals", "(Ljava/lang/Object;)Z"); 101 102 // Push current node on the stack 103 il.append(methodGen.loadCurrentNode()); 104 il.append(SWAP); 105 106 // Overwrite current node with matching node 107 il.append(methodGen.storeCurrentNode()); 108 109 // If pattern not reduced then check kernel 110 if (!_typeChecked) { 111 il.append(methodGen.loadCurrentNode()); 112 final int getType = cpg.addInterfaceMethodref(DOM_INTF, 113 "getExpandedTypeID", 114 "(I)I"); 115 il.append(methodGen.loadDOM()); 116 il.append(methodGen.loadCurrentNode()); 117 il.append(new INVOKEINTERFACE(getType, 2)); 118 il.append(new PUSH(cpg, DTM.PROCESSING_INSTRUCTION_NODE)); 119 _falseList.add(il.append(new IF_ICMPEQ(null))); 120 } 121 122 // Load the requested processing instruction name 123 il.append(new PUSH(cpg, _name)); 124 // Load the current processing instruction's name 125 il.append(methodGen.loadDOM()); 126 il.append(methodGen.loadCurrentNode()); 127 il.append(new INVOKEINTERFACE(gname, 2)); 128 // Compare the two strings 129 il.append(new INVOKEVIRTUAL(cmp)); 130 _falseList.add(il.append(new IFEQ(null))); 131 132 // Compile the expressions within the predicates 133 if (hasPredicates()) { 134 final int n = _predicates.size(); 135 for (int i = 0; i < n; i++) { 136 Predicate pred = (Predicate)_predicates.elementAt(i); 137 Expression exp = pred.getExpr(); 138 exp.translateDesynthesized(classGen, methodGen); 139 _trueList.append(exp._trueList); 140 _falseList.append(exp._falseList); 141 } 142 } 143 144 // Backpatch true list and restore current iterator/node 145 InstructionHandle restore; 146 restore = il.append(methodGen.storeCurrentNode()); 147 backPatchTrueList(restore); 148 BranchHandle skipFalse = il.append(new GOTO(null)); 149 150 // Backpatch false list and restore current iterator/node 151 restore = il.append(methodGen.storeCurrentNode()); 152 backPatchFalseList(restore); 153 _falseList.add(il.append(new GOTO(null))); 154 155 // True list falls through 156 skipFalse.setTarget(il.append(NOP)); 157 } 158 }