1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. 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 package com.sun.org.apache.xalan.internal.xsltc.compiler.util; 22 23 import com.sun.org.apache.bcel.internal.generic.ALOAD; 24 import com.sun.org.apache.bcel.internal.generic.ASTORE; 25 import com.sun.org.apache.bcel.internal.generic.BranchHandle; 26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 27 import com.sun.org.apache.bcel.internal.generic.GOTO; 28 import com.sun.org.apache.bcel.internal.generic.IFEQ; 29 import com.sun.org.apache.bcel.internal.generic.IFNONNULL; 30 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 31 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 32 import com.sun.org.apache.bcel.internal.generic.Instruction; 33 import com.sun.org.apache.bcel.internal.generic.InstructionList; 34 import com.sun.org.apache.bcel.internal.generic.PUSH; 35 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; 36 import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList; 37 38 /** 39 * @author Jacek Ambroziak 40 * @author Santiago Pericas-Geertsen 41 * @LastModified: Oct 2017 42 */ 43 public class StringType extends Type { 44 protected StringType() {} 45 46 public String toString() { 47 return "string"; 48 } 49 50 public boolean identicalTo(Type other) { 51 return this == other; 52 } 53 54 public String toSignature() { 55 return "Ljava/lang/String;"; 56 } 57 58 public boolean isSimple() { 59 return true; 60 } 61 62 public com.sun.org.apache.bcel.internal.generic.Type toJCType() { 63 return com.sun.org.apache.bcel.internal.generic.Type.STRING; 64 } 65 66 /** 67 * Translates a string into an object of internal type <code>type</code>. 68 * The translation to int is undefined since strings are always converted 69 * to reals in arithmetic expressions. 70 * 71 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 72 */ 73 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 74 Type type) { 75 if (type == Type.Boolean) { 76 translateTo(classGen, methodGen, (BooleanType) type); 77 } 78 else if (type == Type.Real) { 79 translateTo(classGen, methodGen, (RealType) type); 80 } 81 else if (type == Type.Reference) { 82 translateTo(classGen, methodGen, (ReferenceType) type); 83 } 84 else if (type == Type.ObjectString) { 85 // NOP -> same representation 86 } 87 else { 88 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 89 toString(), type.toString()); 90 classGen.getParser().reportError(Constants.FATAL, err); 91 } 92 } 93 94 /** 95 * Translates a string into a synthesized boolean. 96 * 97 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 98 */ 99 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 100 BooleanType type) { 101 final InstructionList il = methodGen.getInstructionList(); 102 FlowList falsel = translateToDesynthesized(classGen, methodGen, type); 103 il.append(ICONST_1); 104 final BranchHandle truec = il.append(new GOTO(null)); 105 falsel.backPatch(il.append(ICONST_0)); 106 truec.setTarget(il.append(NOP)); 107 } 108 109 /** 110 * Translates a string into a real by calling stringToReal() from the 111 * basis library. 112 * 113 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 114 */ 115 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 116 RealType type) { 117 final ConstantPoolGen cpg = classGen.getConstantPool(); 118 final InstructionList il = methodGen.getInstructionList(); 119 il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS, 120 STRING_TO_REAL, 121 STRING_TO_REAL_SIG))); 122 } 123 124 /** 125 * Translates a string into a non-synthesized boolean. It does not push a 126 * 0 or a 1 but instead returns branchhandle list to be appended to the 127 * false list. 128 * 129 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized 130 */ 131 public FlowList translateToDesynthesized(ClassGenerator classGen, 132 MethodGenerator methodGen, 133 BooleanType type) { 134 final ConstantPoolGen cpg = classGen.getConstantPool(); 135 final InstructionList il = methodGen.getInstructionList(); 136 137 il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_CLASS, 138 "length", "()I"))); 139 return new FlowList(il.append(new IFEQ(null))); 140 } 141 142 /** 143 * Expects a string on the stack and pushes a boxed string. 144 * Strings are already boxed so the translation is just a NOP. 145 * 146 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 147 */ 148 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 149 ReferenceType type) { 150 methodGen.getInstructionList().append(NOP); 151 } 152 153 /** 154 * Translates a internal string into an external (Java) string. 155 * 156 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateFrom 157 */ 158 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 159 Class<?> clazz) 160 { 161 // Is String <: clazz? I.e. clazz in { String, Object } 162 if (clazz.isAssignableFrom(java.lang.String.class)) { 163 methodGen.getInstructionList().append(NOP); 164 } 165 else { 166 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 167 toString(), clazz.getName()); 168 classGen.getParser().reportError(Constants.FATAL, err); 169 } 170 } 171 172 /** 173 * Translates an external (primitive) Java type into a string. 174 * 175 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateFrom 176 */ 177 public void translateFrom(ClassGenerator classGen, 178 MethodGenerator methodGen, Class<?> clazz) 179 { 180 final ConstantPoolGen cpg = classGen.getConstantPool(); 181 final InstructionList il = methodGen.getInstructionList(); 182 183 if (clazz.getName().equals("java.lang.String")) { 184 // same internal representation, convert null to "" 185 il.append(DUP); 186 final BranchHandle ifNonNull = il.append(new IFNONNULL(null)); 187 il.append(POP); 188 il.append(new PUSH(cpg, "")); 189 ifNonNull.setTarget(il.append(NOP)); 190 } 191 else { 192 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 193 toString(), clazz.getName()); 194 classGen.getParser().reportError(Constants.FATAL, err); 195 } 196 } 197 198 /** 199 * Translates an object of this type to its boxed representation. 200 */ 201 public void translateBox(ClassGenerator classGen, 202 MethodGenerator methodGen) { 203 translateTo(classGen, methodGen, Type.Reference); 204 } 205 206 /** 207 * Translates an object of this type to its unboxed representation. 208 */ 209 public void translateUnBox(ClassGenerator classGen, 210 MethodGenerator methodGen) { 211 methodGen.getInstructionList().append(NOP); 212 } 213 214 /** 215 * Returns the class name of an internal type's external representation. 216 */ 217 public String getClassName() { 218 return(STRING_CLASS); 219 } 220 221 222 public Instruction LOAD(int slot) { 223 return new ALOAD(slot); 224 } 225 226 public Instruction STORE(int slot) { 227 return new ASTORE(slot); 228 } 229 }