1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2001-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: ProcessingInstruction.java,v 1.2.4.1 2005/09/12 11:03:05 pvedula Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.xsltc.compiler; 25 26 import com.sun.org.apache.bcel.internal.generic.ALOAD; 27 import com.sun.org.apache.bcel.internal.generic.ASTORE; 28 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 29 import com.sun.org.apache.bcel.internal.generic.GETFIELD; 30 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 31 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 32 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 33 import com.sun.org.apache.bcel.internal.generic.InstructionList; 34 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; 35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 38 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 39 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 40 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; 41 import com.sun.org.apache.xml.internal.utils.XML11Char; 42 43 /** 44 * @author Jacek Ambroziak 45 * @author Santiago Pericas-Geertsen 46 */ 47 final class ProcessingInstruction extends Instruction { 48 49 private AttributeValue _name; // name treated as AVT (7.1.3) 50 private boolean _isLiteral = false; // specified name is not AVT 51 52 public void parseContents(Parser parser) { 53 final String name = getAttribute("name"); 54 55 if (name.length() > 0) { 56 _isLiteral = Util.isLiteral(name); 57 if (_isLiteral) { 58 if (!XML11Char.isXML11ValidNCName(name)) { 59 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_NCNAME_ERR, name, this); 60 parser.reportError(Constants.ERROR, err); 61 } 62 } 63 _name = AttributeValue.create(this, name, parser); 64 } 65 else 66 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name"); 67 68 if (name.equals("xml")) { 69 reportError(this, parser, ErrorMsg.ILLEGAL_PI_ERR, "xml"); 70 } 71 parseChildren(parser); 72 } 73 74 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 75 _name.typeCheck(stable); 76 typeCheckContents(stable); 77 return Type.Void; 78 } 79 80 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 81 final ConstantPoolGen cpg = classGen.getConstantPool(); 82 final InstructionList il = methodGen.getInstructionList(); 83 84 if (!_isLiteral) { 85 // if the ncname is an AVT, then the ncname has to be checked at runtime if it is a valid ncname 86 LocalVariableGen nameValue = 87 methodGen.addLocalVariable2("nameValue", 88 Util.getJCRefType(STRING_SIG), 89 null); 90 91 // store the name into a variable first so _name.translate only needs to be called once 92 _name.translate(classGen, methodGen); 93 nameValue.setStart(il.append(new ASTORE(nameValue.getIndex()))); 94 il.append(new ALOAD(nameValue.getIndex())); 95 96 // call checkNCName if the name is an AVT 97 final int check = cpg.addMethodref(BASIS_LIBRARY_CLASS, "checkNCName", 98 "(" 99 +STRING_SIG 100 +")V"); 101 il.append(new INVOKESTATIC(check)); 102 103 // Save the current handler base on the stack 104 il.append(methodGen.loadHandler()); 105 il.append(DUP); // first arg to "attributes" call 106 107 // load name value again 108 nameValue.setEnd(il.append(new ALOAD(nameValue.getIndex()))); 109 } else { 110 // Save the current handler base on the stack 111 il.append(methodGen.loadHandler()); 112 il.append(DUP); // first arg to "attributes" call 113 114 // Push attribute name 115 _name.translate(classGen, methodGen);// 2nd arg 116 117 } 118 119 il.append(classGen.loadTranslet()); 120 il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS, 121 "stringValueHandler", 122 STRING_VALUE_HANDLER_SIG))); 123 il.append(DUP); 124 il.append(methodGen.storeHandler()); 125 126 // translate contents with substituted handler 127 translateContents(classGen, methodGen); 128 129 // get String out of the handler 130 il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_VALUE_HANDLER, 131 "getValueOfPI", 132 "()" + STRING_SIG))); 133 // call "processingInstruction" 134 final int processingInstruction = 135 cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, 136 "processingInstruction", 137 "(" + STRING_SIG + STRING_SIG + ")V"); 138 il.append(new INVOKEINTERFACE(processingInstruction, 3)); 139 // Restore old handler base from stack 140 il.append(methodGen.storeHandler()); 141 } 142 }