xref: /trunk/main/autodoc/source/ary/cpp/ca_ce.cxx (revision cdf0e10c)
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