| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| #include <precomp.h> |
| #include "ca_ce.hxx" |
| |
| |
| // NOT FULLY DEFINED SERVICES |
| #include <ary/qualiname.hxx> |
| #include <ary/cpp/inpcontx.hxx> |
| #include <ary/cpp/c_namesp.hxx> |
| #include <ary/cpp/c_class.hxx> |
| #include <ary/cpp/c_enum.hxx> |
| #include <ary/cpp/c_enuval.hxx> |
| #include <ary/cpp/c_funct.hxx> |
| #include <ary/cpp/c_tydef.hxx> |
| #include <ary/cpp/c_type.hxx> |
| #include <ary/cpp/c_vari.hxx> |
| #include <ary/cpp/cp_type.hxx> |
| #include <ary/loc/loc_file.hxx> |
| #include <ary/getncast.hxx> |
| |
| |
| |
| |
| |
| |
| namespace |
| { |
| |
| String Get_NewAnonymousNamespaceName(); |
| String Get_NewAnonymousName( |
| char i_start ); |
| |
| |
| } // anonymous namespace |
| |
| |
| |
| |
| namespace ary |
| { |
| namespace cpp |
| { |
| |
| |
| // KORR_FUTURE |
| // What about namespace visibility ? |
| // Perhaps handle all/some visibility transfer only after parse is complete. |
| void |
| transfer_visibility( const Class * i_owner, |
| CodeEntity & o_child ) |
| { |
| if ( i_owner != 0 ? NOT i_owner->IsVisible() : false ) |
| o_child.Set_InVisible(); |
| } |
| |
| inline const TypePilot & |
| CeAdmin::Types() const |
| { |
| csv_assert(pTypes != 0); |
| return *pTypes; |
| } |
| |
| |
| |
| |
| |
| |
| CeAdmin::CeAdmin(RepositoryPartition & io_myReposyPartition) |
| : aStorage(), |
| pTypes(0), |
| pCppRepositoryPartition(&io_myReposyPartition) |
| { |
| } |
| |
| void |
| CeAdmin::Set_Related(const TypePilot & i_types) |
| { |
| pTypes = &i_types; |
| } |
| |
| CeAdmin::~CeAdmin() |
| { |
| } |
| |
| Namespace & |
| CeAdmin::CheckIn_Namespace( const InputContext & i_context, |
| const String & i_localName ) |
| { |
| const String |
| local_name = NOT i_localName.empty() |
| ? i_localName |
| : Get_NewAnonymousNamespaceName(); |
| Namespace & |
| rParent = i_context.CurNamespace(); |
| Namespace * |
| ret = rParent.Search_LocalNamespace(local_name); |
| if ( ret == 0 ) |
| { |
| ret = &Create_Namespace(rParent, local_name); |
| } |
| return *ret; |
| } |
| |
| Class & |
| CeAdmin::Store_Class( const InputContext & i_context, |
| const String & i_localName, |
| E_ClassKey i_eClassKey ) |
| { |
| const String |
| local_name = i_localName.empty() |
| ? Get_NewAnonymousName( i_eClassKey == CK_class |
| ? 'c' |
| : i_eClassKey == CK_struct |
| ? 's' |
| : 'u' ) |
| : i_localName; |
| |
| Class & |
| ret = * new Class( local_name, |
| i_context.CurOwner().CeId(), |
| i_context.CurProtection(), |
| i_context.CurFile().LeId(), |
| i_eClassKey ); |
| aStorage.Store_Type(ret); |
| i_context.CurOwner().Add_Class(local_name, ret.CeId()); |
| transfer_visibility(i_context.CurClass(), ret); |
| |
| return ret; |
| } |
| |
| Enum & |
| CeAdmin::Store_Enum( const InputContext & i_context, |
| const String & i_localName ) |
| { |
| const String |
| local_name = i_localName.empty() |
| ? Get_NewAnonymousName('e') |
| : i_localName; |
| Enum & |
| ret = * new Enum( local_name, |
| i_context.CurOwner().CeId(), |
| i_context.CurProtection(), |
| i_context.CurFile().LeId() ); |
| aStorage.Store_Type(ret); |
| i_context.CurOwner().Add_Enum(local_name, ret.CeId()); |
| transfer_visibility(i_context.CurClass(), ret); |
| |
| return ret; |
| } |
| |
| Typedef & |
| CeAdmin::Store_Typedef( const InputContext& i_context, |
| const String & i_localName, |
| Type_id i_referredType ) |
| { |
| Typedef & |
| ret = * new Typedef( i_localName, |
| i_context.CurOwner().CeId(), |
| i_context.CurProtection(), |
| i_context.CurFile().LeId(), |
| i_referredType ); |
| aStorage.Store_Type(ret); |
| i_context.CurOwner().Add_Typedef(i_localName, ret.CeId()); |
| transfer_visibility(i_context.CurClass(), ret); |
| |
| return ret; |
| } |
| |
| Function * |
| CeAdmin::Store_Operation( const InputContext & i_context, |
| const String & i_localName, |
| Type_id i_returnType, |
| const std::vector<S_Parameter> & i_parameters, |
| E_Virtuality i_virtuality, |
| E_ConVol i_conVol, |
| FunctionFlags i_flags, |
| bool i_throwExists, |
| const std::vector<Type_id> & i_exceptions ) |
| { |
| Function & |
| ret = * new Function( i_localName, |
| i_context.CurOwner().CeId(), |
| i_context.CurProtection(), |
| i_context.CurFile().LeId(), |
| i_returnType, |
| i_parameters, |
| i_conVol, |
| i_virtuality, |
| i_flags, |
| i_throwExists, |
| i_exceptions ); |
| |
| // Check for double declaration: |
| Ce_id |
| nAlreadyExistingFunction(0); |
| switch ( lhf_CheckAndHandle_DuplicateOperation( |
| nAlreadyExistingFunction, |
| i_context, |
| ret) ) |
| { |
| case df_discard_new: |
| delete &ret; |
| return 0; |
| case df_replace: |
| csv_assert(nAlreadyExistingFunction.IsValid()); |
| aStorage.Replace_Entity( |
| nAlreadyExistingFunction, |
| ret ); |
| break; |
| case df_no: |
| aStorage.Store_Operation(ret); // Now it has a valid id. |
| i_context.CurOwner().Add_Operation( i_localName, ret.CeId(), i_flags.IsStaticMember() ); |
| break; |
| default: |
| csv_assert(false); |
| } |
| |
| transfer_visibility(i_context.CurClass(), ret); |
| if ( i_context.CurProtection() != PROTECT_global ) |
| { |
| Class * |
| pClass = i_context.CurClass(); |
| if ( pClass != 0 AND i_virtuality != VIRTUAL_none) |
| { |
| pClass->UpdateVirtuality(i_virtuality); |
| } |
| } |
| |
| return &ret; |
| } |
| |
| Variable & |
| CeAdmin::Store_Variable( const InputContext& i_context, |
| const String & i_localName, |
| Type_id i_type, |
| VariableFlags i_flags, |
| const String & i_arraySize, |
| const String & i_initValue ) |
| { |
| Variable & |
| ret = * new Variable( i_localName, |
| i_context.CurOwner().CeId(), |
| i_context.CurProtection(), |
| i_context.CurFile().LeId(), |
| i_type, |
| i_flags, |
| i_arraySize, |
| i_initValue ); |
| |
| bool |
| is_const = Types().Find_Type(i_type).IsConst(); |
| aStorage.Store_Datum(ret); |
| i_context.CurOwner().Add_Variable( |
| i_localName, |
| ret.CeId(), |
| is_const, |
| i_flags.IsStaticMember() ); |
| transfer_visibility(i_context.CurClass(), ret); |
| |
| return ret; |
| } |
| |
| EnumValue & |
| CeAdmin::Store_EnumValue( const InputContext & i_context, |
| const String & i_localName, |
| const String & i_initValue ) |
| { |
| Enum * |
| parent = i_context.CurEnum(); |
| csv_assert( parent != 0 ); |
| |
| EnumValue & |
| ret = * new EnumValue( i_localName, |
| parent->CeId(), |
| i_initValue ); |
| aStorage.Store_Datum(ret); |
| parent->Add_Value(ret.CeId()); |
| |
| // KORR also for current enum: |
| transfer_visibility(i_context.CurClass(), ret); |
| |
| return ret; |
| } |
| |
| const Namespace & |
| CeAdmin::GlobalNamespace() const |
| { |
| return ary_cast<Namespace>( aStorage[predefined::ce_GlobalNamespace] ); |
| } |
| |
| const CodeEntity & |
| CeAdmin::Find_Ce(Ce_id i_id) const |
| { |
| return aStorage[i_id]; |
| } |
| |
| const CodeEntity * |
| CeAdmin::Search_Ce(Ce_id i_id) const |
| { |
| return aStorage.Exists(i_id) |
| ? & aStorage[i_id] |
| : (const CodeEntity*)(0); |
| } |
| |
| const CodeEntity * |
| CeAdmin::Search_CeAbsolute( const CodeEntity & i_curScope, |
| const QualifiedName & i_rSearchedName ) const |
| { |
| const symtree::Node<CeNode_Traits> * |
| cur_node = CeNode_Traits::NodeOf_(i_curScope); |
| csv_assert(cur_node != 0); |
| |
| Ce_id |
| ret(0); |
| cur_node->SearchUp( ret, |
| i_rSearchedName.first_namespace(), |
| i_rSearchedName.end_namespace(), |
| i_rSearchedName.LocalName() ); |
| return Search_Ce(ret); |
| } |
| |
| const CodeEntity * |
| CeAdmin::Search_CeLocal( const String & i_localName, |
| bool i_bIsFunction, |
| const Namespace & i_rCurNamespace, |
| const Class * i_pCurClass ) const |
| { |
| // KORR_FUTURE |
| // See if this is correct. |
| |
| Ce_id |
| ret(0); |
| |
| if ( NOT i_bIsFunction ) |
| { |
| CesResultList |
| type_instances = aStorage.TypeIndex().SearchAll(i_localName); |
| CesResultList |
| data_instances = aStorage.DataIndex().SearchAll(i_localName); |
| Ce_id |
| ret1 = Search_MatchingInstance( |
| type_instances, |
| (i_pCurClass |
| ? i_pCurClass->CeId() |
| : i_rCurNamespace.CeId()) |
| ); |
| Ce_id |
| ret2 = Search_MatchingInstance( |
| data_instances, |
| (i_pCurClass |
| ? i_pCurClass->CeId() |
| : i_rCurNamespace.CeId()) |
| ); |
| if (NOT ret2.IsValid()) |
| ret = ret1; |
| else if (NOT ret1.IsValid()) |
| ret = ret2; |
| } |
| else |
| { |
| CesResultList |
| function_instances = aStorage.OperationIndex().SearchAll(i_localName); |
| if ( function_instances.size() == 1 ) |
| ret = *function_instances.begin(); |
| else |
| { |
| ret = Search_MatchingInstance( |
| function_instances, |
| (i_pCurClass |
| ? i_pCurClass->CeId() |
| : i_rCurNamespace.CeId()) |
| ); |
| } |
| } |
| |
| if ( ret.IsValid() ) |
| return & Find_Ce(ret); |
| |
| return 0; |
| } |
| |
| void |
| CeAdmin::Get_QualifiedName( StreamStr & o_rOut, |
| const String & i_localName, |
| Ce_id i_nOwner, |
| const char * i_sDelimiter ) const |
| { |
| if ( i_localName.empty() OR NOT i_nOwner.IsValid() ) |
| return; |
| |
| const CodeEntity * |
| pOwner = & Find_Ce( i_nOwner ); |
| if ( is_type<Enum>(*pOwner) ) |
| pOwner = &Find_Ce( Ce_id(pOwner->Owner()) ); |
| |
| Get_QualifiedName( o_rOut, |
| pOwner->LocalName(), |
| Ce_id(pOwner->Owner()), |
| i_sDelimiter ); |
| o_rOut |
| << i_sDelimiter |
| << i_localName; |
| } |
| |
| void |
| CeAdmin::Get_SignatureText( StreamStr & o_rOut, |
| const OperationSignature & i_signature, |
| const StringVector * i_sParameterNames ) const |
| { |
| OperationSignature::ParameterTypeList::const_iterator |
| it = i_signature.Parameters().begin(); |
| OperationSignature::ParameterTypeList::const_iterator |
| it_end = i_signature.Parameters().end(); |
| |
| const StringVector aDummy; |
| StringVector::const_iterator |
| itName = i_sParameterNames != 0 |
| ? i_sParameterNames->begin() |
| : aDummy.begin(); |
| StringVector::const_iterator |
| itName_end = i_sParameterNames != 0 |
| ? i_sParameterNames->end() |
| : aDummy.end(); |
| |
| bool |
| bEmpty = (it == it_end); |
| if (NOT bEmpty) |
| { |
| o_rOut << "( "; |
| Types().Get_TypeText(o_rOut, *it); |
| if (itName != itName_end) |
| o_rOut << " " << (*itName); |
| |
| for ( ++it; it != it_end; ++it ) |
| { |
| o_rOut << ", "; |
| Types().Get_TypeText(o_rOut, *it); |
| if (itName != itName_end) |
| { |
| ++itName; |
| if (itName != itName_end) |
| o_rOut << " " << (*itName); |
| } |
| } |
| o_rOut << " )"; |
| } |
| else |
| { |
| o_rOut << "( )"; |
| } |
| |
| if ( intt(i_signature.ConVol()) & intt(ary::cpp::CONVOL_const) ) |
| o_rOut << " const"; |
| if ( intt(i_signature.ConVol()) & intt(ary::cpp::CONVOL_volatile) ) |
| o_rOut << " volatile"; |
| } |
| |
| CesResultList |
| CeAdmin::Search_TypeName(const String & i_sName) const |
| { |
| return aStorage.TypeIndex().SearchAll(i_sName); |
| } |
| |
| Namespace & |
| CeAdmin::GlobalNamespace() |
| { |
| return ary_cast<Namespace>( aStorage[predefined::ce_GlobalNamespace] ); |
| } |
| |
| CeAdmin::E_DuplicateFunction |
| CeAdmin::lhf_CheckAndHandle_DuplicateOperation( |
| Ce_id & o_existentFunction, |
| const InputContext & i_context, |
| const Function & i_newFunction ) |
| { |
| if (i_context.CurProtection() != PROTECT_global) |
| { |
| // Assume, there will be no duplicates within the same class. |
| |
| // KORR_FUTURE |
| // Assumption may be wrong in case of #defines providing different |
| // versions for different compilers. |
| return df_no; |
| } |
| |
| std::vector<Ce_id> |
| aOperationsWithSameName; |
| i_context.CurNamespace().Search_LocalOperations( |
| aOperationsWithSameName, |
| i_newFunction.LocalName() ); |
| |
| for ( std::vector<Ce_id>::const_iterator |
| it = aOperationsWithSameName.begin(); |
| it != aOperationsWithSameName.end(); |
| ++it ) |
| { |
| const Function & |
| rFunction = ary_cast<Function>(aStorage[*it]); |
| if ( rFunction.LocalName() == i_newFunction.LocalName() |
| AND rFunction.Signature() == i_newFunction.Signature() ) |
| { |
| if (NOT rFunction.IsIdentical(i_newFunction)) |
| { |
| // KORR_FUTURE Make this more detailed. |
| Cerr() << "Non identical function with same signature " |
| << "found: " |
| << i_context.CurNamespace().LocalName() |
| << "::" |
| << i_newFunction.LocalName() |
| << "(..)" |
| << Endl(); |
| } |
| o_existentFunction = rFunction.CeId(); |
| if (rFunction.Docu().Data() == 0) |
| return df_replace; |
| else |
| return df_discard_new; |
| } |
| } // end for |
| |
| return df_no; |
| } |
| |
| Namespace & |
| CeAdmin::Create_Namespace( Namespace & o_parent, |
| const String & i_localName ) |
| { |
| DYN Namespace & |
| ret = *new Namespace(i_localName, o_parent); |
| aStorage.Store_Entity(ret); |
| o_parent.Add_LocalNamespace(ret); |
| return ret; |
| } |
| |
| Ce_id |
| CeAdmin::Search_MatchingInstance( CesResultList i_list, |
| Ce_id i_owner ) const |
| { |
| // KORR |
| // Multiple results? |
| |
| for ( CesList::const_iterator it = i_list.begin(); |
| it != i_list.end(); |
| ++it ) |
| { |
| const CodeEntity & |
| ce = aStorage[*it]; |
| if ( ce.Owner() == i_owner) |
| { |
| return *it; |
| } |
| } |
| return Ce_id(0); |
| } |
| |
| |
| |
| } // namespace cpp |
| } // namespace ary |
| |
| |
| |
| namespace |
| { |
| |
| uintt G_nLastFreeAnonymousNamespaceNr = 0; |
| uintt G_nLastFreeAnonymousEntityNr = 0; |
| |
| String |
| Get_NewAnonymousNamespaceName() |
| { |
| StreamLock |
| sl(100); |
| return String( sl() |
| << "namespace_anonymous_" |
| << ++G_nLastFreeAnonymousNamespaceNr |
| << csv::c_str ); |
| |
| } |
| |
| String |
| Get_NewAnonymousName(char i_cStart) |
| { |
| StreamLock |
| sl(100); |
| return String( sl() |
| << i_cStart |
| << "_Anonymous__" |
| << ++G_nLastFreeAnonymousEntityNr |
| << c_str ); |
| } |
| |
| |
| |
| } // namespace anonymous |