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