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.ConstantPoolGen;
25 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
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.PUSH;
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 
36 /**
37  * @author Jacek Ambroziak
38  * @author Santiago Pericas-Geertsen
39  * @author Morten Jorgensen
40  */
41 final class ValueOf extends Instruction {
42     private Expression _select;
43     private boolean _escaping = true;
44     private boolean _isString = false;
45 
display(int indent)46     public void display(int indent) {
47         indent(indent);
48         Util.println("ValueOf");
49         indent(indent + IndentIncrement);
50         Util.println("select " + _select.toString());
51     }
52 
parseContents(Parser parser)53     public void parseContents(Parser parser) {
54         _select = parser.parseExpression(this, "select", null);
55 
56         // make sure required attribute(s) have been set
57         if (_select.isDummy()) {
58             reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select");
59             return;
60         }
61         final String str = getAttribute("disable-output-escaping");
62         if ((str != null) && (str.equals("yes"))) _escaping = false;
63     }
64 
typeCheck(SymbolTable stable)65     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
66         Type type = _select.typeCheck(stable);
67 
68         // Prefer to handle the value as a node; fall back to String, otherwise
69         if (type != null && !type.identicalTo(Type.Node)) {
70             /***
71              *** %HZ% Would like to treat result-tree fragments in the same
72              *** %HZ% way as node sets for value-of, but that's running into
73              *** %HZ% some snags.  Instead, they'll be converted to String
74             if (type.identicalTo(Type.ResultTree)) {
75                 _select = new CastExpr(new CastExpr(_select, Type.NodeSet),
76                                        Type.Node);
77             } else
78             ***/
79             if (type.identicalTo(Type.NodeSet)) {
80                 _select = new CastExpr(_select, Type.Node);
81             } else {
82                 _isString = true;
83                 if (!type.identicalTo(Type.String)) {
84                     _select = new CastExpr(_select, Type.String);
85                 }
86                 _isString = true;
87             }
88         }
89         return Type.Void;
90     }
91 
translate(ClassGenerator classGen, MethodGenerator methodGen)92     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
93         final ConstantPoolGen cpg = classGen.getConstantPool();
94         final InstructionList il = methodGen.getInstructionList();
95         final int setEscaping = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
96                                                           "setEscaping","(Z)Z");
97 
98         // Turn off character escaping if so is wanted.
99         if (!_escaping) {
100             il.append(methodGen.loadHandler());
101             il.append(new PUSH(cpg,false));
102             il.append(new INVOKEINTERFACE(setEscaping,2));
103         }
104 
105         // Translate the contents.  If the value is a string, use the
106         // translet.characters(String, TranslatOutputHandler) method.
107         // Otherwise, the value is a node, and the
108         // dom.characters(int node, TransletOutputHandler) method can dispatch
109         // the string value of the node to the output handler more efficiently.
110         if (_isString) {
111             final int characters = cpg.addMethodref(TRANSLET_CLASS,
112                                                     CHARACTERSW,
113                                                     CHARACTERSW_SIG);
114 
115             il.append(classGen.loadTranslet());
116             _select.translate(classGen, methodGen);
117             il.append(methodGen.loadHandler());
118             il.append(new INVOKEVIRTUAL(characters));
119         } else {
120             final int characters = cpg.addInterfaceMethodref(DOM_INTF,
121                                                              CHARACTERS,
122                                                              CHARACTERS_SIG);
123 
124             il.append(methodGen.loadDOM());
125             _select.translate(classGen, methodGen);
126             il.append(methodGen.loadHandler());
127             il.append(new INVOKEINTERFACE(characters, 3));
128         }
129 
130         // Restore character escaping setting to whatever it was.
131         if (!_escaping) {
132             il.append(methodGen.loadHandler());
133             il.append(SWAP);
134             il.append(new INVOKEINTERFACE(setEscaping,2));
135             il.append(POP);
136         }
137     }
138 }
139