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