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.ALOAD; 25 import com.sun.org.apache.bcel.internal.generic.ASTORE; 26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 27 import com.sun.org.apache.bcel.internal.generic.GETFIELD; 28 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 29 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 30 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 31 import com.sun.org.apache.bcel.internal.generic.InstructionList; 32 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; 33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 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.xalan.internal.xsltc.compiler.util.Util; 39 import com.sun.org.apache.xml.internal.utils.XML11Char; 40 41 /** 42 * @author Jacek Ambroziak 43 * @author Santiago Pericas-Geertsen 44 */ 45 final class ProcessingInstruction extends Instruction { 46 47 private AttributeValue _name; // name treated as AVT (7.1.3) 48 private boolean _isLiteral = false; // specified name is not AVT 49 50 public void parseContents(Parser parser) { 51 final String name = getAttribute("name"); 52 53 if (name.length() > 0) { 54 _isLiteral = Util.isLiteral(name); 55 if (_isLiteral) { 56 if (!XML11Char.isXML11ValidNCName(name)) { 57 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_NCNAME_ERR, name, this); 58 parser.reportError(Constants.ERROR, err); 59 } 60 } 61 _name = AttributeValue.create(this, name, parser); 62 } 63 else 64 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name"); 65 66 if (name.equals("xml")) { 67 reportError(this, parser, ErrorMsg.ILLEGAL_PI_ERR, "xml"); 68 } 69 parseChildren(parser); 70 } 71 72 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 73 _name.typeCheck(stable); 74 typeCheckContents(stable); 75 return Type.Void; 76 } 77 78 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 79 final ConstantPoolGen cpg = classGen.getConstantPool(); 80 final InstructionList il = methodGen.getInstructionList(); 81 82 if (!_isLiteral) { 83 // if the ncname is an AVT, then the ncname has to be checked at runtime if it is a valid ncname 84 LocalVariableGen nameValue = 85 methodGen.addLocalVariable2("nameValue", 86 Util.getJCRefType(STRING_SIG), 87 null); 88 89 // store the name into a variable first so _name.translate only needs to be called once 90 _name.translate(classGen, methodGen); 91 nameValue.setStart(il.append(new ASTORE(nameValue.getIndex()))); 92 il.append(new ALOAD(nameValue.getIndex())); 93 94 // call checkNCName if the name is an AVT 95 final int check = cpg.addMethodref(BASIS_LIBRARY_CLASS, "checkNCName", 96 "(" 97 +STRING_SIG 98 +")V"); 99 il.append(new INVOKESTATIC(check)); 100 101 // Save the current handler base on the stack 102 il.append(methodGen.loadHandler()); 103 il.append(DUP); // first arg to "attributes" call 104 105 // load name value again 106 nameValue.setEnd(il.append(new ALOAD(nameValue.getIndex()))); 107 } else { 108 // Save the current handler base on the stack 109 il.append(methodGen.loadHandler()); 110 il.append(DUP); // first arg to "attributes" call 111 112 // Push attribute name 113 _name.translate(classGen, methodGen);// 2nd arg 114 115 } 116 117 il.append(classGen.loadTranslet()); 118 il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS, 119 "stringValueHandler", 120 STRING_VALUE_HANDLER_SIG))); 121 il.append(DUP); 122 il.append(methodGen.storeHandler()); 123 124 // translate contents with substituted handler 125 translateContents(classGen, methodGen); 126 127 // get String out of the handler 128 il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_VALUE_HANDLER, 129 "getValueOfPI", 130 "()" + STRING_SIG))); 131 // call "processingInstruction" 132 final int processingInstruction = 133 cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, 134 "processingInstruction", 135 "(" + STRING_SIG + STRING_SIG + ")V"); 136 il.append(new INVOKEINTERFACE(processingInstruction, 3)); 137 // Restore old handler base from stack 138 il.append(methodGen.storeHandler()); 139 } 140 }