/*
* 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.
*/
package org.jacorb.idl;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Vector;
/**
* @author Gerald Brose
*/
public class Member
extends Declaration
{
public TypeSpec type_spec;
/**
this list initially set by the parser but later flattened so that
each member only has a single declarator. The list will be null after
calling parse()!
*/
SymbolList declarators;
public Vector extendVector;
public TypeDeclaration containingType;
public Declarator declarator;
public Member( int num )
{
super( num );
}
public void setPackage( String s )
{
s = parser.pack_replace( s );
if( pack_name.length() > 0 )
pack_name = s + "." + pack_name;
else
pack_name = s;
type_spec.setPackage( s );
if ( declarators != null )
declarators.setPackage( s );
}
public void setEnclosingSymbol( IdlSymbol s )
{
enclosing_symbol = s;
type_spec.setEnclosingSymbol( s );
for( Enumeration e = declarators.v.elements(); e.hasMoreElements(); )
( (Declarator)e.nextElement() ).setEnclosingSymbol( s );
}
public void setContainingType( TypeDeclaration t )
{
containingType = t;
}
/**
* must be set by MemberList before parsing
*/
public void setExtendVector( Vector v )
{
extendVector = v;
}
/**
* Creates a new Member that is similar to this one,
* but only for declarator d.
*/
public Member extractMember( Declarator d )
{
Member result = new Member( new_num() );
result.declarator = d;
return result;
}
/**
* Parsing members means creating new members for definitions
* with more than one declarator.
*/
public void parse()
{
boolean clone_and_parse = true;
if( extendVector == null )
{
lexer.restorePosition(myPosition);
parser.fatal_error ("Internal Compiler Error: extendVector not set.", token);
}
if( type_spec.typeSpec() instanceof ScopedName )
{
token = type_spec.typeSpec().get_token();
String name = type_spec.typeSpec().toString();
type_spec = ( (ScopedName)type_spec.typeSpec() ).resolvedTypeSpec();
enclosing_symbol.addImportedName( name, type_spec );
if( type_spec instanceof AliasTypeSpec )
{
AliasTypeSpec aliasTS = (AliasTypeSpec)type_spec;
TypeSpec originalType = aliasTS.originalType ();
if( originalType instanceof SequenceType )
{
SequenceType sequenceTS = (SequenceType)originalType;
if( sequenceTS.elementTypeSpec().typeName().equals( containingType.typeName()) )
{
sequenceTS.setRecursive ();
}
}
}
clone_and_parse = false;
if( type_spec instanceof ConstrTypeSpec )
{
if( ( (ConstrTypeSpec)type_spec.typeSpec() ).c_type_spec instanceof StructType )
{
if(
( (ConstrTypeSpec)type_spec.typeSpec() ).c_type_spec.typeName().equals( containingType.typeName() )
)
{
parser.fatal_error( "Illegal type recursion (use sequence<" +
containingType.typeName() + "> instead)", token );
}
}
}
}
else if( type_spec.typeSpec() instanceof SequenceType )
{
TypeSpec ts = ( (SequenceType)type_spec.typeSpec() ).elementTypeSpec().typeSpec();
SequenceType seqTs = (SequenceType)type_spec.typeSpec();
while( ts instanceof SequenceType )
{
seqTs = (SequenceType)ts;
ts = ( (SequenceType)ts.typeSpec() ).elementTypeSpec().typeSpec();
}
if( ScopedName.isRecursionScope( ts.typeName() ) )
{
seqTs.setRecursive();
}
}
else if( type_spec instanceof ConstrTypeSpec )
{
type_spec.parse();
}
String tokName = null;
if( token != null && token.line_val != null )
{
tokName = token.line_val.trim();
if( tokName.length() == 0 )
{
tokName = null;
}
}
for( Enumeration e = declarators.v.elements(); e.hasMoreElements(); )
{
Declarator declarator = (Declarator)e.nextElement();
String declaratorName = declarator.name();
if( tokName != null )
{
if (org.jacorb.idl.parser.strict_names)
{
// check for name clashes strictly (i.e. case insensitive)
if( declaratorName.equalsIgnoreCase( tokName ) )
{
parser.fatal_error( "Declarator " + declaratorName +
" already defined in scope.", token );
}
}
else
{
// check for name clashes only loosely (i.e. case sensitive)
if( declaratorName.equals( tokName ) )
{
parser.fatal_error( "Declarator " + declaratorName +
" already defined in scope.", token );
}
}
}
// we don't parse the declarator itself
// as that would result in its name getting defined
// we define the declarator's name as a type name indirectly
// through the cloned type specs.
Member m = extractMember( declarator );
TypeSpec ts = type_spec.typeSpec();
/* create a separate type spec copy for every declarator
if the type spec is a new type definition, i.e. a
struct, enum, union, sequence or the declarator is
an array declarator
*/
if( clone_and_parse || declarator.d instanceof ArrayDeclarator )
{
/* arrays need special treatment */
if( declarator.d instanceof ArrayDeclarator )
{
ts = new ArrayTypeSpec( new_num(), ts, (ArrayDeclarator)declarator.d, pack_name );
ts.parse();
}
else if( !( ts instanceof BaseType ) )
{
ts = (TypeSpec)ts.clone();
if( !( ts instanceof ConstrTypeSpec ) )
{
ts.set_name( declarator.name() );
}
/* important: only parse type specs once (we do it for the last
declarator only) */
if( !e.hasMoreElements() )
{
ts.parse();
}
}
}
// else
if( !( declarator.d instanceof ArrayDeclarator ) )
{
try
{
NameTable.define( containingType + "." + declarator.name(),
IDLTypes.DECLARATOR );
}
catch( NameAlreadyDefined nad )
{
parser.fatal_error( "Declarator " + declarator.name() +
" already defined in scope.", token );
}
}
/* if the type spec is a scoped name, it is already parsed and
* the type name is defined
*/
m.type_spec = ts;
m.pack_name = this.pack_name;
m.name = declaratorName;
extendVector.addElement( m );
}
declarators = null;
}
/**
*
*/
public void print( PrintWriter ps )
{
member_print( ps, "\tpublic " );
}
/**
*
*/
public void member_print( PrintWriter ps, String prefix )
{
/* only print members that are not interfaces */
if( ( type_spec.typeSpec() instanceof ConstrTypeSpec &&
!( ( ( (ConstrTypeSpec)type_spec.typeSpec() ).c_type_spec.declaration()
instanceof Interface ) ||
( ( (ConstrTypeSpec)type_spec.typeSpec() ).c_type_spec.declaration()
instanceof Value ) ) ) ||
type_spec.typeSpec() instanceof SequenceType ||
type_spec.typeSpec() instanceof ArrayTypeSpec )
{
type_spec.print( ps );
}
if( type_spec.typeSpec().toString().equals("java.lang.String"))
{
ps.print( prefix + type_spec.toString() + " " + declarator.toString() + " = \"\";" );
}
else
{
ps.print( prefix + type_spec.toString() + " " + declarator.toString() + ";" );
}
}
public TypeSpec typeSpec()
{
return type_spec.typeSpec();
}
}