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