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();
}
}