diff options
Diffstat (limited to 'ACE/TAO/TAO_IDL/ast/ast_type.cpp')
-rw-r--r-- | ACE/TAO/TAO_IDL/ast/ast_type.cpp | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/ACE/TAO/TAO_IDL/ast/ast_type.cpp b/ACE/TAO/TAO_IDL/ast/ast_type.cpp new file mode 100644 index 00000000000..b4cb660d48f --- /dev/null +++ b/ACE/TAO/TAO_IDL/ast/ast_type.cpp @@ -0,0 +1,574 @@ +// $Id$ + +/* + +COPYRIGHT + +Copyright 1992, 1993, 1994 Sun Microsystems, Inc. Printed in the United +States of America. All Rights Reserved. + +This product is protected by copyright and distributed under the following +license restricting its use. + +The Interface Definition Language Compiler Front End (CFE) is made +available for your use provided that you include this license and copyright +notice on all media and documentation and the software program in which +this product is incorporated in whole or part. You may copy and extend +functionality (but may not remove functionality) of the Interface +Definition Language CFE without charge, but you are not authorized to +license or distribute it to anyone else except as part of a product or +program developed by you or with the express written consent of Sun +Microsystems, Inc. ("Sun"). + +The names of Sun Microsystems, Inc. and any of its subsidiaries or +affiliates may not be used in advertising or publicity pertaining to +distribution of Interface Definition Language CFE as permitted herein. + +This license is effective until terminated by Sun for failure to comply +with this license. Upon termination, you shall destroy or return all code +and documentation for the Interface Definition Language CFE. + +INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF +ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS +FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF +DEALING, USAGE OR TRADE PRACTICE. + +INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT +ANY OBLIGATION ON THE PART OF Sun OR ANY OF ITS SUBSIDIARIES OR AFFILIATES +TO ASSIST IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT. + +SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH +RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY +INTERFACE DEFINITION LANGUAGE CFE OR ANY PART THEREOF. + +IN NO EVENT WILL SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR +ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL +DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +Use, duplication, or disclosure by the government is subject to +restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in +Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR +52.227-19. + +Sun, Sun Microsystems and the Sun logo are trademarks or registered +trademarks of Sun Microsystems, Inc. + +SunSoft, Inc. +2550 Garcia Avenue +Mountain View, California 94043 + +NOTE: + +SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are +trademarks or registered trademarks of Sun Microsystems, Inc. + +*/ + +// AST_Type is the base class for all AST classes which represent +// IDL type constructs. + +#include "ast_type.h" +#include "ast_typedef.h" +#include "ast_visitor.h" +#include "utl_identifier.h" +#include "idl_defines.h" +#include "nr_extern.h" +#include "ace/Log_Msg.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_Memory.h" + +ACE_RCSID (ast, + ast_type, + "$Id$") + +AST_Type::AST_Type (void) + : COMMON_Base (), + AST_Decl (), + ifr_added_ (0), + ifr_fwd_added_ (0), + size_type_ (AST_Type::SIZE_UNKNOWN), + has_constructor_ (0), + nested_type_name_ (0), + in_recursion_ (-1), + recursing_in_legal_pk_ (false) +{ +} + +AST_Type::AST_Type (AST_Decl::NodeType nt, + UTL_ScopedName *n) + : COMMON_Base (), + AST_Decl (nt, + n), + ifr_added_ (0), + ifr_fwd_added_ (0), + size_type_ (AST_Type::SIZE_UNKNOWN), + has_constructor_ (0), + nested_type_name_ (0), + in_recursion_ (-1), + recursing_in_legal_pk_ (false) +{ +} + +AST_Type::~AST_Type (void) +{ +} + +// Public operations. + +// Return our size type. +AST_Type::SIZE_TYPE +AST_Type::size_type (void) +{ + if (this->size_type_ == AST_Type::SIZE_UNKNOWN) + { + (void) this->compute_size_type (); + } + + return this->size_type_; +} + +// Set our size type and that of all our ancestors. +void +AST_Type::size_type (AST_Type::SIZE_TYPE st) +{ + // Size type can be VARIABLE or FIXED. + if (this->size_type_ == AST_Type::SIZE_UNKNOWN) // not set yet + { + this->size_type_ = st; // set it + } + else if ((this->size_type_ == AST_Type::FIXED) + && (st == AST_Type::VARIABLE)) + { + // Once we are VARIABLE, we cannot be FIXED. But if we were FIXED and then + // get overwritten to VARIABLE, it is fine. Such a situation occurs only + // when setting the sizes of structures and unions. + this->size_type_ = st; + } +} + +// Compute the size type of the node in question +int +AST_Type::compute_size_type (void) +{ + return 0; +} + +bool +AST_Type::in_recursion (ACE_Unbounded_Queue<AST_Type *> &) +{ + // By default we are not involved in recursion. + return 0; +} + +bool +AST_Type::is_defined (void) +{ + // AST_Interface, AST_Structure, and AST_Union will + // override this, as will AST_InterfaceFwd, etc. + return 1; +} + +bool +AST_Type::ifr_added (void) +{ + return this->ifr_added_; +} + +void +AST_Type::ifr_added (bool val) +{ + this->ifr_added_ = val; +} + +bool +AST_Type::ifr_fwd_added (void) +{ + return this->ifr_fwd_added_; +} + +void +AST_Type::ifr_fwd_added (bool val) +{ + this->ifr_fwd_added_ = val; +} + +bool +AST_Type::has_constructor (void) +{ + return this->has_constructor_; +} + +void +AST_Type::has_constructor (bool value) +{ + // Similarly to be_decl::size_type_, once this + // gets set to true, we don't want it to + // change back. + if (this->has_constructor_ == 0) + { + this->has_constructor_ = value; + } +} + +// This code works. However, whether we should generate the +// ACE_NESTED_CLASS macro or not should be based on an option to the +// compiler. The previous version generated a relative path. +// This version always generates ACE_NESTED_CLASS, (leave ace/ACE.h and friends +// do the porting) +// +// Caution: returns the same buffer pointer even if the contents may change +// in the next call. (return std::string anyone?) +// +// Return the type name using the ACE_NESTED_CLASS macro + +const char * +AST_Type::nested_type_name (AST_Decl *use_scope, + const char *suffix, + const char *prefix) +{ + return this->nested_name (this->local_name ()->get_string (), + this->full_name (), + use_scope, + suffix, + prefix); +} + +AST_Type * +AST_Type::unaliased_type (void) +{ + AST_Type *t = this; + AST_Typedef *td = 0; + AST_Decl::NodeType nt = this->node_type (); + + while (nt == AST_Decl::NT_typedef) + { + td = AST_Typedef::narrow_from_decl (t); + t = td->base_type (); + nt = t->node_type (); + } + + return t; +} + +bool +AST_Type::legal_for_primary_key (void) const +{ + return true; +} + +// This is the real thing used by the method above. +const char * +AST_Type::nested_name (const char* local_name, + const char* full_name, + AST_Decl *use_scope, + const char *suffix, + const char *prefix) +{ + // Some compilers do not like generating a fully scoped name for a type that + // was defined in the same enclosing scope in which it was defined. For such, + // we emit a macro defined in the ACE library. + // + + // The tricky part here is that it is not enough to check if the + // typename we are using was defined in the current scope. But we + // need to ensure that it was not defined in any of our ancestor + // scopes as well. If that is the case, then we can generate a fully + // scoped name for that type, else we use the ACE_NESTED_CLASS macro. + + // Thus we need some sort of relative name to be generated. + + if (this->nested_type_name_ == 0) + { + ACE_NEW_RETURN (this->nested_type_name_, + char[NAMEBUFSIZE], + 0); + } + + // Hold the fully scoped name. + char def_name [NAMEBUFSIZE]; + char use_name [NAMEBUFSIZE]; + + // These point to the prev, curr and next component in the scope. + char *def_curr = def_name; + char *def_next = 0; + char *use_curr = use_name; + char *use_next = 0; + + // How many chars to compare. + int len_to_match = 0; + + // Initialize the buffers. + ACE_OS::memset (this->nested_type_name_, + '\0', + NAMEBUFSIZE); + + ACE_OS::memset (def_name, + '\0', + NAMEBUFSIZE); + + ACE_OS::memset (use_name, + '\0', + NAMEBUFSIZE); + + // Traverse every component of the def_scope and use_scope beginning at the + // root and proceeding towards the leaf trying to see if the components + // match. Continue until there is a match and keep accumulating the path + // traversed. This forms the first argument to the ACE_NESTED_CLASS + // macro. Whenever there is no match, the remaining components of the + // def_scope form the second argument. + + // This adds the global double colon for type names using the canonical + // CORBA namespace, replacing the ad hoc spot + // generations of "::" here and there, which have now been removed. + UTL_Scope *s = this->defined_in (); + AST_Decl *def_scope = s != 0 ? ScopeAsDecl (s) : 0; + + // TypeCode is a special case for predefined types, since it's + // defined in the CORBA module. + bool in_root = + (def_scope != 0 && def_scope->node_type () == AST_Decl::NT_root) + || ((this->node_type () == AST_Decl::NT_pre_defined + && ACE_OS::strcmp (this->flat_name (), "CORBA_TypeCode") == 0)); + + ACE_CString fname (this->full_name ()); + bool corba_type = fname.find ("CORBA::") == 0; + + if (in_root && corba_type) + { + ACE_OS::strcat (this->nested_type_name_, "::"); + } + + if (def_scope != 0 && !in_root && use_scope != 0) + // If both scopes exist and that we are not in the root scope. + { + ACE_OS::strcpy (def_name, + def_scope->full_name ()); + + ACE_OS::strcpy (use_name, + use_scope->full_name ()); + + // Find the first occurrence of a :: and advance + // the next pointers accordingly. + def_next = ACE_OS::strstr (def_curr, "::"); + use_next = ACE_OS::strstr (use_curr, "::"); + + // If the scopes are identical, don't supply them. + if (ACE_OS::strcmp (def_name, use_name) == 0) + { + if (prefix != 0) + { + ACE_OS::strcat (this->nested_type_name_, + prefix); + } + + ACE_OS::strcat (this->nested_type_name_, + local_name); + if (suffix != 0) + { + ACE_OS::strcat (this->nested_type_name_, + suffix); + } + + return this->nested_type_name_; + } + + if (def_next != 0) + { + len_to_match = + static_cast<int> (ACE_OS::strlen (def_curr)) - + static_cast<int> (ACE_OS::strlen (def_next)); + } + else + { + len_to_match = static_cast<int> (ACE_OS::strlen (def_curr)); + } + + if (use_next != 0) + { + const int len = + static_cast<int> (ACE_OS::strlen (use_curr)) - + static_cast<int> (ACE_OS::strlen (use_next)); + + if (len > len_to_match) + { + len_to_match = len; + } + } + else + { + const int len = static_cast<int> (ACE_OS::strlen (use_curr)); + + if (len > len_to_match) + { + len_to_match = len; + } + } + + if (ACE_OS::strncmp (def_curr, + use_curr, + len_to_match) + == 0) + { + // Initialize the first argument. + ACE_OS::strncat (this->nested_type_name_, + def_curr, + len_to_match); + + // Shift the current scopes to the next level. + def_curr = (def_next ? (def_next + 2) : 0); // Skip the :: + use_curr = (use_next ? (use_next + 2) : 0); // Skip the :: + + while (def_curr && use_curr) + { + // Find the first occurrence of a :: and advance the + // next pointers accordingly. + def_next = ACE_OS::strstr (def_curr, "::"); + use_next = ACE_OS::strstr (use_curr, "::"); + + if (def_next != 0) + { + len_to_match = + static_cast<int> (ACE_OS::strlen (def_curr)) - + static_cast<int> (ACE_OS::strlen (def_next)); + } + else + { + len_to_match = static_cast<int> (ACE_OS::strlen (def_curr)); + } + + if (use_next != 0) + { + int len = + static_cast<int> (ACE_OS::strlen (use_curr)) - + static_cast<int> (ACE_OS::strlen (use_next)); + + if (len > len_to_match) + { + len_to_match = len; + } + } + else + { + const int len = static_cast<int> (ACE_OS::strlen (use_curr)); + + if (len > len_to_match) + { + len_to_match = len; + } + } + + if (ACE_OS::strncmp (def_curr, + use_curr, + len_to_match) + == 0) + { + // They have same prefix, append to arg1. + ACE_OS::strcat (this->nested_type_name_, + "::"); + + ACE_OS::strncat (this->nested_type_name_, + def_curr, + len_to_match); + + def_curr = (def_next ? (def_next + 2) : 0); // Skip the :: + use_curr = (use_next ? (use_next + 2) : 0); // Skip the :: + } + else + { + // No match. This is the end of the first argument. Get out + // of the loop as no more comparisons are necessary. + break; + } + } + + // Start the 2nd argument of the macro. + ACE_OS::strcat (this->nested_type_name_, "::"); + + // Copy the remaining def_name (if any are left). + if (def_curr != 0) + { + ACE_OS::strcat (this->nested_type_name_, + def_curr); + + ACE_OS::strcat (this->nested_type_name_, + "::"); + } + + // Append our local name. + if (prefix != 0) + { + ACE_OS::strcat (this->nested_type_name_, prefix); + } + + ACE_OS::strcat (this->nested_type_name_, + local_name); + + if (suffix != 0) + { + ACE_OS::strcat (this->nested_type_name_, + suffix); + } + + return this->nested_type_name_; + } // End of if the root prefixes match. + } + + // Otherwise just emit our full_name. + if (prefix != 0) + { + ACE_OS::strcat (this->nested_type_name_, prefix); + } + + ACE_OS::strcat (this->nested_type_name_, + full_name); + + if (suffix != 0) + { + ACE_OS::strcat (this->nested_type_name_, + suffix); + } + + return this->nested_type_name_; +} + +bool +AST_Type::match_names (AST_Type *t, ACE_Unbounded_Queue<AST_Type *> &list) +{ + for (ACE_Unbounded_Queue_Iterator<AST_Type *> iter (list); + !iter.done (); + (void) iter.advance ()) + { + // Queue element. + AST_Type **temp = 0; + + (void) iter.next (temp); + + if (!ACE_OS::strcmp (t->full_name (), + (*temp)->full_name ())) + { + return true; + } + } + + return false; +} + +int +AST_Type::ast_accept (ast_visitor *visitor) +{ + return visitor->visit_type (this); +} + +void +AST_Type::destroy (void) +{ + delete [] this->nested_type_name_; + this->nested_type_name_ = 0; + + this->AST_Decl::destroy (); +} + + + +IMPL_NARROW_FROM_DECL(AST_Type) |