package org.jacorb.idl; /* * JacORB - a free Java ORB * * Copyright (C) 1997-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.io.PrintWriter; import java.math.BigInteger; import java.util.logging.Level; import org.jacorb.idl.runtime.int_token; import org.jacorb.idl.runtime.long_token; import org.jacorb.idl.runtime.token; /** * @author Gerald Brose */ public class Literal extends IdlSymbol { private static final BigInteger IDL_SHORT_MIN = new BigInteger ("-32768"); private static final BigInteger IDL_SHORT_MAX = new BigInteger ("32768"); private static final BigInteger IDL_UNSIGNED_MIN = new BigInteger ("0"); private static final BigInteger IDL_UNSIGNED_SHORT_MAX = new BigInteger ("65535"); private static final BigInteger IDL_LONG_MIN = new BigInteger ("-2147483648"); private static final BigInteger IDL_LONG_MAX = new BigInteger ("2147483647"); private static final BigInteger IDL_UNSIGNED_LONG_MAX = new BigInteger ("4294967295"); private static final BigInteger IDL_LONG_LONG_MIN = new BigInteger ("-9223372036854775808"); private static final BigInteger IDL_LONG_LONG_MAX = new BigInteger ("9223372036854775807"); private static final BigInteger IDL_UNSIGNED_LONG_LONG_MAX = new BigInteger ("18446744073709551615"); public String string; public boolean wide; public token primitiveToken; private ConstDecl declared_in; public Literal( int num ) { super( num ); } public void setDeclaration( ConstDecl declared_in ) { this.declared_in = declared_in; } public void parse() { // const expressions containing literals can be declared // outside cons declarations (e.g, in sequence bounds), // but we care only for const declarations here. if( declared_in != null ) { TypeSpec ts = declared_in.const_type.symbol.typeSpec(); // If its an alias check the actual type not the alias if (ts instanceof AliasTypeSpec) { ts = ((AliasTypeSpec)ts).originalType (); } if( parser.logger.isLoggable(Level.WARNING) ) parser.logger.log(Level.WARNING, "Literal " + ts.getClass().getName() + " " + ( primitiveToken != null? primitiveToken.getClass().getName() :"<no token>" )); // At first check the float types and strings if( ts instanceof FloatPtType && !( primitiveToken instanceof org.jacorb.idl.runtime.float_token ) ) { parser.error( "Expecting float/double constant!" ); } else if( ts instanceof FixedPointConstType && !( primitiveToken instanceof fixed_token ) ) { parser.error( "Expecting fixed point constant (perhaps a missing \"d\")!" ); } else if( ts instanceof StringType ) { if( wide && !( (StringType)ts ).isWide() ) parser.error( "Illegal assignment of wide string constant to string!" ); } else if( ts instanceof IntType ) { // COS578 constant value check was reworked // convert constant for the comparison BigInteger value = null; if( primitiveToken instanceof int_token || primitiveToken instanceof long_token || primitiveToken instanceof fixed_token ) { value = new BigInteger( string ); } else { parser.error( "Illegal assignment to '" + TypeSpec.getIDLType (ts) + "' of '" + string + "' value" ); // do not check further conditions return; } // check the unsigned values first if( ( (IntType)ts ).unsigned ) { if( value.compareTo( IDL_UNSIGNED_MIN ) < 0 ) { parser.error( "Value " + value.toString() + " is too small for unsigned type" ); } else if( ts instanceof LongLongType ) { if( value.compareTo( IDL_UNSIGNED_LONG_LONG_MAX ) > 0 ) { parser.error( "Value " + value.toString() + " is too big for unsigned long long" ); } else if( primitiveToken instanceof fixed_token ) { primitiveToken = new long_token ( ((fixed_token)primitiveToken).sym, ((fixed_token)primitiveToken).fixed_val.longValue () ); string = Long.toString (((long_token)primitiveToken).long_val); } } else if( ts instanceof LongType ) { if( value.compareTo (IDL_UNSIGNED_LONG_MAX) > 0 ) { parser.error( "Value " + value.toString() + " is too big for unsigned long" ); } else if( primitiveToken instanceof long_token ) { primitiveToken = new int_token ( ((long_token)primitiveToken).sym, (int)((long_token)primitiveToken).long_val ); string = Integer.toString (((int_token)primitiveToken).int_val); } } else if( ts instanceof ShortType && value.compareTo( IDL_UNSIGNED_SHORT_MAX ) > 0 ) { parser.error( "Value " + value.toString() + " is too big for unsigned long" ); } } // then checking the signed type ranges else if( ts instanceof LongLongType ) { if( value.compareTo( IDL_LONG_LONG_MIN ) < 0 ) { parser.error( "Value " + value.toString() + " is too small for long long type" ); } else if( value.compareTo( IDL_LONG_LONG_MAX ) > 0 ) { parser.error( "Value " + value.toString() + " is too big for long long type" ); } } else if( ts instanceof LongType ) { if( value.compareTo (IDL_LONG_MIN) < 0 ) { parser.error( "Value " + value.toString() + " is too small for long type" ); } else if( value.compareTo (IDL_LONG_MAX) > 0 ) { parser.error( "Value " + value.toString() + " is too big for long type" ); } } else if (ts instanceof ShortType) { if( value.compareTo (IDL_SHORT_MIN) < 0 ) { parser.error( "Value " + value.toString() + " is too small for short type" ); } else if( value.compareTo (IDL_SHORT_MAX) > 0 ) { parser.error( "Value " + value.toString() + " is too big for short type" ); } } } } } public String toString() { String result = string; if (primitiveToken instanceof org.jacorb.idl.runtime.long_token) { if (string.indexOf( '.' ) > 0 ) { result = (string + 'D'); } else { result = (string + 'L'); } } return escapeBackslash (result); } public void print( PrintWriter ps ) { ps.print( escapeBackslash( string )); } /** * Doubles up instances of the backslash character in a * string, to avoid them being interpreted as escape sequences * * @param name a <code>String</code> value * @return string */ public static String escapeBackslash( String name ) { StringBuffer result = new StringBuffer(); char[] chrs = name.toCharArray(); // Don't bother escaping if we have "xxx" if( chrs[ 0 ] == '\"' ) { return name; } for( int i = 0; i < chrs.length; i++ ) { switch( chrs[ i ] ) { case '\n': { result.append( '\\' ); result.append( 'n' ); break; } case '\t': { result.append( '\\' ); result.append( 't' ); break; } case '\013': { result.append( '\\' ); result.append( "013" ); break; } case '\b': { result.append( '\\' ); result.append( 'b' ); break; } case '\r': { result.append( '\\' ); result.append( 'r' ); break; } case '\f': { result.append( '\\' ); result.append( 'f' ); break; } case '\007': { result.append( '\\' ); result.append( "007" ); break; } case '\\': { result.append( '\\' ); result.append( '\\' ); break; } case '\0': { result.append( '\\' ); result.append( '0' ); break; } case '\'': { if( i == 1 ) { result.append( '\\' ); result.append( '\'' ); } else { result.append( chrs[ i ] ); } break; } case '\"': { if( i == 1 ) { result.append( '\\' ); result.append( '\"' ); } else { result.append( chrs[ i ] ); } break; } default: { result.append( chrs[ i ] ); } } } return result.toString(); } }