1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 #include <precomp.h> 30 #include "ca_ce.hxx" 31 32 33 // NOT FULLY DEFINED SERVICES 34 #include <ary/qualiname.hxx> 35 #include <ary/cpp/inpcontx.hxx> 36 #include <ary/cpp/c_namesp.hxx> 37 #include <ary/cpp/c_class.hxx> 38 #include <ary/cpp/c_enum.hxx> 39 #include <ary/cpp/c_enuval.hxx> 40 #include <ary/cpp/c_funct.hxx> 41 #include <ary/cpp/c_tydef.hxx> 42 #include <ary/cpp/c_type.hxx> 43 #include <ary/cpp/c_vari.hxx> 44 #include <ary/cpp/cp_type.hxx> 45 #include <ary/loc/loc_file.hxx> 46 #include <ary/getncast.hxx> 47 48 49 50 51 52 53 namespace 54 { 55 56 String Get_NewAnonymousNamespaceName(); 57 String Get_NewAnonymousName( 58 char i_start ); 59 60 61 } // anonymous namespace 62 63 64 65 66 namespace ary 67 { 68 namespace cpp 69 { 70 71 72 // KORR_FUTURE 73 // What about namespace visibility ? 74 // Perhaps handle all/some visibility transfer only after parse is complete. 75 void 76 transfer_visibility( const Class * i_owner, 77 CodeEntity & o_child ) 78 { 79 if ( i_owner != 0 ? NOT i_owner->IsVisible() : false ) 80 o_child.Set_InVisible(); 81 } 82 83 inline const TypePilot & 84 CeAdmin::Types() const 85 { 86 csv_assert(pTypes != 0); 87 return *pTypes; 88 } 89 90 91 92 93 94 95 CeAdmin::CeAdmin(RepositoryPartition & io_myReposyPartition) 96 : aStorage(), 97 pTypes(0), 98 pCppRepositoryPartition(&io_myReposyPartition) 99 { 100 } 101 102 void 103 CeAdmin::Set_Related(const TypePilot & i_types) 104 { 105 pTypes = &i_types; 106 } 107 108 CeAdmin::~CeAdmin() 109 { 110 } 111 112 Namespace & 113 CeAdmin::CheckIn_Namespace( const InputContext & i_context, 114 const String & i_localName ) 115 { 116 const String 117 local_name = NOT i_localName.empty() 118 ? i_localName 119 : Get_NewAnonymousNamespaceName(); 120 Namespace & 121 rParent = i_context.CurNamespace(); 122 Namespace * 123 ret = rParent.Search_LocalNamespace(local_name); 124 if ( ret == 0 ) 125 { 126 ret = &Create_Namespace(rParent, local_name); 127 } 128 return *ret; 129 } 130 131 Class & 132 CeAdmin::Store_Class( const InputContext & i_context, 133 const String & i_localName, 134 E_ClassKey i_eClassKey ) 135 { 136 const String 137 local_name = i_localName.empty() 138 ? Get_NewAnonymousName( i_eClassKey == CK_class 139 ? 'c' 140 : i_eClassKey == CK_struct 141 ? 's' 142 : 'u' ) 143 : i_localName; 144 145 Class & 146 ret = * new Class( local_name, 147 i_context.CurOwner().CeId(), 148 i_context.CurProtection(), 149 i_context.CurFile().LeId(), 150 i_eClassKey ); 151 aStorage.Store_Type(ret); 152 i_context.CurOwner().Add_Class(local_name, ret.CeId()); 153 transfer_visibility(i_context.CurClass(), ret); 154 155 return ret; 156 } 157 158 Enum & 159 CeAdmin::Store_Enum( const InputContext & i_context, 160 const String & i_localName ) 161 { 162 const String 163 local_name = i_localName.empty() 164 ? Get_NewAnonymousName('e') 165 : i_localName; 166 Enum & 167 ret = * new Enum( local_name, 168 i_context.CurOwner().CeId(), 169 i_context.CurProtection(), 170 i_context.CurFile().LeId() ); 171 aStorage.Store_Type(ret); 172 i_context.CurOwner().Add_Enum(local_name, ret.CeId()); 173 transfer_visibility(i_context.CurClass(), ret); 174 175 return ret; 176 } 177 178 Typedef & 179 CeAdmin::Store_Typedef( const InputContext& i_context, 180 const String & i_localName, 181 Type_id i_referredType ) 182 { 183 Typedef & 184 ret = * new Typedef( i_localName, 185 i_context.CurOwner().CeId(), 186 i_context.CurProtection(), 187 i_context.CurFile().LeId(), 188 i_referredType ); 189 aStorage.Store_Type(ret); 190 i_context.CurOwner().Add_Typedef(i_localName, ret.CeId()); 191 transfer_visibility(i_context.CurClass(), ret); 192 193 return ret; 194 } 195 196 Function * 197 CeAdmin::Store_Operation( const InputContext & i_context, 198 const String & i_localName, 199 Type_id i_returnType, 200 const std::vector<S_Parameter> & i_parameters, 201 E_Virtuality i_virtuality, 202 E_ConVol i_conVol, 203 FunctionFlags i_flags, 204 bool i_throwExists, 205 const std::vector<Type_id> & i_exceptions ) 206 { 207 Function & 208 ret = * new Function( i_localName, 209 i_context.CurOwner().CeId(), 210 i_context.CurProtection(), 211 i_context.CurFile().LeId(), 212 i_returnType, 213 i_parameters, 214 i_conVol, 215 i_virtuality, 216 i_flags, 217 i_throwExists, 218 i_exceptions ); 219 220 // Check for double declaration: 221 Ce_id 222 nAlreadyExistingFunction(0); 223 switch ( lhf_CheckAndHandle_DuplicateOperation( 224 nAlreadyExistingFunction, 225 i_context, 226 ret) ) 227 { 228 case df_discard_new: 229 delete &ret; 230 return 0; 231 case df_replace: 232 csv_assert(nAlreadyExistingFunction.IsValid()); 233 aStorage.Replace_Entity( 234 nAlreadyExistingFunction, 235 ret ); 236 break; 237 case df_no: 238 aStorage.Store_Operation(ret); // Now it has a valid id. 239 i_context.CurOwner().Add_Operation( i_localName, ret.CeId(), i_flags.IsStaticMember() ); 240 break; 241 default: 242 csv_assert(false); 243 } 244 245 transfer_visibility(i_context.CurClass(), ret); 246 if ( i_context.CurProtection() != PROTECT_global ) 247 { 248 Class * 249 pClass = i_context.CurClass(); 250 if ( pClass != 0 AND i_virtuality != VIRTUAL_none) 251 { 252 pClass->UpdateVirtuality(i_virtuality); 253 } 254 } 255 256 return &ret; 257 } 258 259 Variable & 260 CeAdmin::Store_Variable( const InputContext& i_context, 261 const String & i_localName, 262 Type_id i_type, 263 VariableFlags i_flags, 264 const String & i_arraySize, 265 const String & i_initValue ) 266 { 267 Variable & 268 ret = * new Variable( i_localName, 269 i_context.CurOwner().CeId(), 270 i_context.CurProtection(), 271 i_context.CurFile().LeId(), 272 i_type, 273 i_flags, 274 i_arraySize, 275 i_initValue ); 276 277 bool 278 is_const = Types().Find_Type(i_type).IsConst(); 279 aStorage.Store_Datum(ret); 280 i_context.CurOwner().Add_Variable( 281 i_localName, 282 ret.CeId(), 283 is_const, 284 i_flags.IsStaticMember() ); 285 transfer_visibility(i_context.CurClass(), ret); 286 287 return ret; 288 } 289 290 EnumValue & 291 CeAdmin::Store_EnumValue( const InputContext & i_context, 292 const String & i_localName, 293 const String & i_initValue ) 294 { 295 Enum * 296 parent = i_context.CurEnum(); 297 csv_assert( parent != 0 ); 298 299 EnumValue & 300 ret = * new EnumValue( i_localName, 301 parent->CeId(), 302 i_initValue ); 303 aStorage.Store_Datum(ret); 304 parent->Add_Value(ret.CeId()); 305 306 // KORR also for current enum: 307 transfer_visibility(i_context.CurClass(), ret); 308 309 return ret; 310 } 311 312 const Namespace & 313 CeAdmin::GlobalNamespace() const 314 { 315 return ary_cast<Namespace>( aStorage[predefined::ce_GlobalNamespace] ); 316 } 317 318 const CodeEntity & 319 CeAdmin::Find_Ce(Ce_id i_id) const 320 { 321 return aStorage[i_id]; 322 } 323 324 const CodeEntity * 325 CeAdmin::Search_Ce(Ce_id i_id) const 326 { 327 return aStorage.Exists(i_id) 328 ? & aStorage[i_id] 329 : (const CodeEntity*)(0); 330 } 331 332 const CodeEntity * 333 CeAdmin::Search_CeAbsolute( const CodeEntity & i_curScope, 334 const QualifiedName & i_rSearchedName ) const 335 { 336 const symtree::Node<CeNode_Traits> * 337 cur_node = CeNode_Traits::NodeOf_(i_curScope); 338 csv_assert(cur_node != 0); 339 340 Ce_id 341 ret(0); 342 cur_node->SearchUp( ret, 343 i_rSearchedName.first_namespace(), 344 i_rSearchedName.end_namespace(), 345 i_rSearchedName.LocalName() ); 346 return Search_Ce(ret); 347 } 348 349 const CodeEntity * 350 CeAdmin::Search_CeLocal( const String & i_localName, 351 bool i_bIsFunction, 352 const Namespace & i_rCurNamespace, 353 const Class * i_pCurClass ) const 354 { 355 // KORR_FUTURE 356 // See if this is correct. 357 358 Ce_id 359 ret(0); 360 361 if ( NOT i_bIsFunction ) 362 { 363 CesResultList 364 type_instances = aStorage.TypeIndex().SearchAll(i_localName); 365 CesResultList 366 data_instances = aStorage.DataIndex().SearchAll(i_localName); 367 Ce_id 368 ret1 = Search_MatchingInstance( 369 type_instances, 370 (i_pCurClass 371 ? i_pCurClass->CeId() 372 : i_rCurNamespace.CeId()) 373 ); 374 Ce_id 375 ret2 = Search_MatchingInstance( 376 data_instances, 377 (i_pCurClass 378 ? i_pCurClass->CeId() 379 : i_rCurNamespace.CeId()) 380 ); 381 if (NOT ret2.IsValid()) 382 ret = ret1; 383 else if (NOT ret1.IsValid()) 384 ret = ret2; 385 } 386 else 387 { 388 CesResultList 389 function_instances = aStorage.OperationIndex().SearchAll(i_localName); 390 if ( function_instances.size() == 1 ) 391 ret = *function_instances.begin(); 392 else 393 { 394 ret = Search_MatchingInstance( 395 function_instances, 396 (i_pCurClass 397 ? i_pCurClass->CeId() 398 : i_rCurNamespace.CeId()) 399 ); 400 } 401 } 402 403 if ( ret.IsValid() ) 404 return & Find_Ce(ret); 405 406 return 0; 407 } 408 409 void 410 CeAdmin::Get_QualifiedName( StreamStr & o_rOut, 411 const String & i_localName, 412 Ce_id i_nOwner, 413 const char * i_sDelimiter ) const 414 { 415 if ( i_localName.empty() OR NOT i_nOwner.IsValid() ) 416 return; 417 418 const CodeEntity * 419 pOwner = & Find_Ce( i_nOwner ); 420 if ( is_type<Enum>(*pOwner) ) 421 pOwner = &Find_Ce( Ce_id(pOwner->Owner()) ); 422 423 Get_QualifiedName( o_rOut, 424 pOwner->LocalName(), 425 Ce_id(pOwner->Owner()), 426 i_sDelimiter ); 427 o_rOut 428 << i_sDelimiter 429 << i_localName; 430 } 431 432 void 433 CeAdmin::Get_SignatureText( StreamStr & o_rOut, 434 const OperationSignature & i_signature, 435 const StringVector * i_sParameterNames ) const 436 { 437 OperationSignature::ParameterTypeList::const_iterator 438 it = i_signature.Parameters().begin(); 439 OperationSignature::ParameterTypeList::const_iterator 440 it_end = i_signature.Parameters().end(); 441 442 const StringVector aDummy; 443 StringVector::const_iterator 444 itName = i_sParameterNames != 0 445 ? i_sParameterNames->begin() 446 : aDummy.begin(); 447 StringVector::const_iterator 448 itName_end = i_sParameterNames != 0 449 ? i_sParameterNames->end() 450 : aDummy.end(); 451 452 bool 453 bEmpty = (it == it_end); 454 if (NOT bEmpty) 455 { 456 o_rOut << "( "; 457 Types().Get_TypeText(o_rOut, *it); 458 if (itName != itName_end) 459 o_rOut << " " << (*itName); 460 461 for ( ++it; it != it_end; ++it ) 462 { 463 o_rOut << ", "; 464 Types().Get_TypeText(o_rOut, *it); 465 if (itName != itName_end) 466 { 467 ++itName; 468 if (itName != itName_end) 469 o_rOut << " " << (*itName); 470 } 471 } 472 o_rOut << " )"; 473 } 474 else 475 { 476 o_rOut << "( )"; 477 } 478 479 if ( intt(i_signature.ConVol()) & intt(ary::cpp::CONVOL_const) ) 480 o_rOut << " const"; 481 if ( intt(i_signature.ConVol()) & intt(ary::cpp::CONVOL_volatile) ) 482 o_rOut << " volatile"; 483 } 484 485 CesResultList 486 CeAdmin::Search_TypeName(const String & i_sName) const 487 { 488 return aStorage.TypeIndex().SearchAll(i_sName); 489 } 490 491 Namespace & 492 CeAdmin::GlobalNamespace() 493 { 494 return ary_cast<Namespace>( aStorage[predefined::ce_GlobalNamespace] ); 495 } 496 497 CeAdmin::E_DuplicateFunction 498 CeAdmin::lhf_CheckAndHandle_DuplicateOperation( 499 Ce_id & o_existentFunction, 500 const InputContext & i_context, 501 const Function & i_newFunction ) 502 { 503 if (i_context.CurProtection() != PROTECT_global) 504 { 505 // Assume, there will be no duplicates within the same class. 506 507 // KORR_FUTURE 508 // Assumption may be wrong in case of #defines providing different 509 // versions for different compilers. 510 return df_no; 511 } 512 513 std::vector<Ce_id> 514 aOperationsWithSameName; 515 i_context.CurNamespace().Search_LocalOperations( 516 aOperationsWithSameName, 517 i_newFunction.LocalName() ); 518 519 for ( std::vector<Ce_id>::const_iterator 520 it = aOperationsWithSameName.begin(); 521 it != aOperationsWithSameName.end(); 522 ++it ) 523 { 524 const Function & 525 rFunction = ary_cast<Function>(aStorage[*it]); 526 if ( rFunction.LocalName() == i_newFunction.LocalName() 527 AND rFunction.Signature() == i_newFunction.Signature() ) 528 { 529 if (NOT rFunction.IsIdentical(i_newFunction)) 530 { 531 // KORR_FUTURE Make this more detailed. 532 Cerr() << "Non identical function with same signature " 533 << "found: " 534 << i_context.CurNamespace().LocalName() 535 << "::" 536 << i_newFunction.LocalName() 537 << "(..)" 538 << Endl(); 539 } 540 o_existentFunction = rFunction.CeId(); 541 if (rFunction.Docu().Data() == 0) 542 return df_replace; 543 else 544 return df_discard_new; 545 } 546 } // end for 547 548 return df_no; 549 } 550 551 Namespace & 552 CeAdmin::Create_Namespace( Namespace & o_parent, 553 const String & i_localName ) 554 { 555 DYN Namespace & 556 ret = *new Namespace(i_localName, o_parent); 557 aStorage.Store_Entity(ret); 558 o_parent.Add_LocalNamespace(ret); 559 return ret; 560 } 561 562 Ce_id 563 CeAdmin::Search_MatchingInstance( CesResultList i_list, 564 Ce_id i_owner ) const 565 { 566 // KORR 567 // Multiple results? 568 569 for ( CesList::const_iterator it = i_list.begin(); 570 it != i_list.end(); 571 ++it ) 572 { 573 const CodeEntity & 574 ce = aStorage[*it]; 575 if ( ce.Owner() == i_owner) 576 { 577 return *it; 578 } 579 } 580 return Ce_id(0); 581 } 582 583 584 585 } // namespace cpp 586 } // namespace ary 587 588 589 590 namespace 591 { 592 593 uintt G_nLastFreeAnonymousNamespaceNr = 0; 594 uintt G_nLastFreeAnonymousEntityNr = 0; 595 596 String 597 Get_NewAnonymousNamespaceName() 598 { 599 StreamLock 600 sl(100); 601 return String( sl() 602 << "namespace_anonymous_" 603 << ++G_nLastFreeAnonymousNamespaceNr 604 << csv::c_str ); 605 606 } 607 608 String 609 Get_NewAnonymousName(char i_cStart) 610 { 611 StreamLock 612 sl(100); 613 return String( sl() 614 << i_cStart 615 << "_Anonymous__" 616 << ++G_nLastFreeAnonymousEntityNr 617 << c_str ); 618 } 619 620 621 622 } // namespace anonymous 623