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.INVOKEINTERFACE;
28 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
29 import com.sun.org.apache.bcel.internal.generic.InstructionList;
30 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
31 import com.sun.org.apache.bcel.internal.generic.NEW;
32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeType;
35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
38 
39 /**
40  * @author Jacek Ambroziak
41  * @author Santiago Pericas-Geertsen
42  */
43 final class AbsoluteLocationPath extends Expression {
44     private Expression _path;   // may be null
45 
AbsoluteLocationPath()46     public AbsoluteLocationPath() {
47         _path = null;
48     }
49 
AbsoluteLocationPath(Expression path)50     public AbsoluteLocationPath(Expression path) {
51         _path = path;
52         if (path != null) {
53             _path.setParent(this);
54         }
55     }
56 
setParser(Parser parser)57     public void setParser(Parser parser) {
58         super.setParser(parser);
59         if (_path != null) {
60             _path.setParser(parser);
61         }
62     }
63 
getPath()64     public Expression getPath() {
65         return(_path);
66     }
67 
toString()68     public String toString() {
69         return "AbsoluteLocationPath(" +
70             (_path != null ? _path.toString() : "null") + ')';
71     }
72 
typeCheck(SymbolTable stable)73     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
74         if (_path != null) {
75             final Type ptype = _path.typeCheck(stable);
76             if (ptype instanceof NodeType) {            // promote to node-set
77                 _path = new CastExpr(_path, Type.NodeSet);
78             }
79         }
80         return _type = Type.NodeSet;
81     }
82 
translate(ClassGenerator classGen, MethodGenerator methodGen)83     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
84         final ConstantPoolGen cpg = classGen.getConstantPool();
85         final InstructionList il = methodGen.getInstructionList();
86         if (_path != null) {
87             final int initAI = cpg.addMethodref(ABSOLUTE_ITERATOR,
88                                                 "<init>",
89                                                 "("
90                                                 + NODE_ITERATOR_SIG
91                                                 + ")V");
92 
93             // Compile relative path iterator(s)
94             //
95             // Backwards branches are prohibited if an uninitialized object is
96             // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed.
97             // We don't know whether this code might contain backwards branches,
98             // so we mustn't create the new object until after we've created
99             // this argument to its constructor.  Instead we calculate the
100             // value of the argument to the constructor first, store it in
101             // a temporary variable, create the object and reload the argument
102             // from the temporary to avoid the problem.
103             _path.translate(classGen, methodGen);
104             LocalVariableGen relPathIterator
105                     = methodGen.addLocalVariable("abs_location_path_tmp",
106                                        Util.getJCRefType(NODE_ITERATOR_SIG),
107                                        null, null);
108             relPathIterator.setStart(
109                     il.append(new ASTORE(relPathIterator.getIndex())));
110 
111             // Create new AbsoluteIterator
112             il.append(new NEW(cpg.addClass(ABSOLUTE_ITERATOR)));
113             il.append(DUP);
114             relPathIterator.setEnd(
115                     il.append(new ALOAD(relPathIterator.getIndex())));
116 
117             // Initialize AbsoluteIterator with iterator from the stack
118             il.append(new INVOKESPECIAL(initAI));
119         }
120         else {
121             final int gitr = cpg.addInterfaceMethodref(DOM_INTF,
122                                                        "getIterator",
123                                                        "()"+NODE_ITERATOR_SIG);
124             il.append(methodGen.loadDOM());
125             il.append(new INVOKEINTERFACE(gitr, 1));
126         }
127     }
128 }
129