1
// This file is part of PUMA.
2
// Copyright (C) 1999-2003 The PUMA developer team.
4
// This program is free software; you can redistribute it and/or
5
// modify it under the terms of the GNU General Public License as
6
// published by the Free Software Foundation; either version 2 of
7
// the License, or (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public
15
// License along with this program; if not, write to the Free
16
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19
#include "Puma/CEnumeratorInfo.h"
20
#include "Puma/CTemplateParamInfo.h"
21
#include "Puma/CClassDatabase.h"
22
#include "Puma/CAttributeInfo.h"
23
#include "Puma/CFunctionInfo.h"
24
#include "Puma/CArgumentInfo.h"
25
#include "Puma/CTypedefInfo.h"
26
#include "Puma/CTemplateInstance.h"
27
#include "Puma/CTemplateInfo.h"
28
#include "Puma/CObjectInfo.h"
29
#include "Puma/CScopeInfo.h"
30
#include "Puma/CUnionInfo.h"
31
#include "Puma/CClassInfo.h"
32
#include "Puma/CFileInfo.h"
33
#include "Puma/CEnumInfo.h"
34
#include "Puma/CTypeInfo.h"
35
#include "Puma/CUsingInfo.h"
36
#include "Puma/CNamespaceInfo.h"
37
#include "Puma/ErrorStream.h"
38
#include "Puma/CProject.h"
39
#include "Puma/Token.h"
40
#include "Puma/Unit.h"
49
CClassDatabase::~CClassDatabase () {
50
for (int i = 0; i < _Files.length (); i++)
51
delete (CFileInfo*)_Files[i];
52
// delete functions infos of built-in operators
53
multimap<int,CFunctionInfo*>::iterator iter;
54
for (iter = _builtin_ops.begin (); iter != _builtin_ops.end (); ++iter)
58
void CClassDatabase::Insert (CObjectInfo *info) {
59
if (! info || ! info->Name ()) return;
61
if (info->ClassInfo ())
62
_Classes.append (info);
63
else if (info->UnionInfo ())
64
_Unions.append (info);
65
else if (info->EnumInfo ())
67
else if (info->TypedefInfo ())
68
_Typedefs.append (info);
69
else if (info->FunctionInfo ())
70
_Functions.append (info);
71
else if (info->FileInfo ())
79
void CClassDatabase::Remove (CObjectInfo *info) {
81
if (info->ClassInfo ()) {
82
for (long i = ClassInfos (); i > 0; i--)
83
if (_Classes.fetch (i-1) == info)
84
_Classes.remove (i-1);
85
} else if (info->UnionInfo ()) {
86
for (long i = UnionInfos (); i > 0; i--)
87
if (_Unions.fetch (i-1) == info)
89
} else if (info->EnumInfo ()) {
90
for (long i = EnumInfos (); i > 0; i--)
91
if (_Enums.fetch (i-1) == info)
93
} else if (info->TypedefInfo ()) {
94
for (long i = TypedefInfos (); i > 0; i--)
95
if (_Typedefs.fetch (i-1) == info)
96
_Typedefs.remove (i-1);
97
} else if (info->FunctionInfo ()) {
98
for (long i = FunctionInfos (); i > 0; i--)
99
if (_Functions.fetch (i-1) == info)
100
_Functions.remove (i-1);
101
} else if (info->FileInfo ()) {
102
for (long i = FileInfos (); i > 0; i--)
103
if (_Files.fetch (i-1) == info)
109
CFunctionInfo *CClassDatabase::BuiltinOperator (const char *name, int tok,
110
CTypeInfo *rtype, CTypeInfo *t0, CTypeInfo *t1) {
115
// first check if this built-in operator already exists ...
116
multimap<int,CFunctionInfo*>::iterator iter, lower, upper;
117
lower = _builtin_ops.lower_bound (tok);
118
upper = _builtin_ops.upper_bound (tok);
119
// check all exisiting operators with the right token type
120
for (iter = lower; iter != upper; ++iter) {
122
args = info->TypeInfo ()->ArgTypes ();
123
// same number of arguments?
124
if (args->Entries () == (unsigned)((t0?1:0) + (t1?1:0))) {
125
// same parameter type list
126
if ((t0 ? *t0 == *args->Entry (0) : true) &&
127
(t1 ? *t1 == *args->Entry (1) : true)) {
128
if (t0) CTypeInfo::Destroy (t0);
129
if (t1) CTypeInfo::Destroy (t1);
130
if (rtype) CTypeInfo::Destroy (rtype);
131
return info; // operator already exists
136
// the operator object has to be created ...
139
rtype = &CTYPE_UNDEFINED;
141
// parameter type list
142
args = new CTypeList ((t0?1:0)+(t1?1:0));
143
if (t0) args->AddEntry (t0);
144
if (t1) args->AddEntry (t1);
146
// operator function type
147
type = new CTypeFunction (rtype, args, true);
150
info = new CFunctionInfo;
152
info->isOperator (true);
153
info->ObjectInfo ()->TypeInfo (type);
154
type->VirtualType ()->TypeFunction ()->FunctionInfo (info);
156
// create function parameters
157
if (t0) CreateParameter (info, t0);
158
if (t1) CreateParameter (info, t1);
160
// insert the object as a regular object into the class database
163
// insert the object into the map
164
_builtin_ops.insert (multimap<int,CFunctionInfo*>::value_type (tok, info));
169
void CClassDatabase::CreateParameter (CFunctionInfo *fi, CTypeInfo *type) const {
171
info = fi->newArgument ();
172
info->Name ("<noname>");
173
info->Storage (CStorage::CLASS_AUTOMATIC);
174
info->TypeInfo (type->Duplicate ());
177
CObjectInfo *CClassDatabase::ObjectInfo (Token *token) const {
178
unsigned infos = ObjectInfos ();
179
for (unsigned i = 0; i < infos; i++) {
180
CObjectInfo *info = ObjectInfo (i);
181
if (! info->FileInfo ())
182
if (*info->SourceInfo () == token)
185
return (CObjectInfo*)0;
188
CObjectInfo *CClassDatabase::ObjectInfo (CT_Token *token) const {
189
unsigned infos = ObjectInfos ();
190
for (unsigned i = 0; i < infos; i++) {
191
CObjectInfo *info = ObjectInfo (i);
192
if (! info->FileInfo ())
193
if (*info->SourceInfo () == token)
196
return (CObjectInfo*)0;
199
CObjectInfo *CClassDatabase::ObjectInfo (unsigned i) const {
200
if (i < ClassInfos ()) return ClassInfo (i);
201
else i = i - ClassInfos ();
202
if (i < UnionInfos ()) return UnionInfo (i);
203
else i = i - UnionInfos ();
204
if (i < EnumInfos ()) return EnumInfo (i);
205
else i = i - EnumInfos ();
206
if (i < TypedefInfos ()) return TypedefInfo (i);
207
else i = i - TypedefInfos ();
208
if (i < FunctionInfos ()) return FunctionInfo (i);
209
else i = i - FunctionInfos ();
210
if (i < FileInfos ()) return FileInfo (i);
211
return (CObjectInfo*)0;
215
void CClassDatabase::Dump (ostream &out, int level) const {
216
unsigned files = FileInfos ();
220
for (unsigned i = 0; i < files; i++) {
222
out << "file " << count++ << " : " << file->Name () << endl;
223
Dump (out, file, 0, level);
227
void CClassDatabase::Dump (ostream &out, CStructure *scope, int ind, int level) const {
230
if (! scope || (ind / 4) > level)
233
// Template parameter (print on template scope only)
234
num = scope->TemplateParams ();
235
if (num && scope->TemplateInfo ()) {
236
indent (out, ind+2); out << num << " template parameters:" << endl;
237
for (unsigned j = 0; j < num; j++)
238
DumpTemplateParam (out, scope->TemplateParam (j), ind);
242
num = scope->Types ();
244
indent (out, ind+2); out << num << " types:" << endl;
245
for (unsigned j = 0; j < num; j++)
246
DumpType (out, scope->Type (j), ind);
250
num = scope->Namespaces ();
252
indent (out, ind+2); out << num << " namespaces:" << endl;
253
for (unsigned j = 0; j < num; j++)
254
DumpNamespace (out, scope->Namespace (j), ind);
258
num = scope->Usings ();
260
indent (out, ind+2); out << num << " usings:" << endl;
261
for (unsigned j = 0; j < num; j++)
262
DumpUsing (out, scope->Using (j), ind);
266
num = scope->Attributes ();
268
indent (out, ind+2); out << num << " attributes: " << endl;
269
for (unsigned j = 0; j < num; j++)
270
DumpAttribute (out, scope->Attribute (j), ind);
274
num = scope->Functions ();
276
indent (out, ind+2); out << num << " functions:" << endl;
277
for (unsigned j = 0; j < num; j++)
278
DumpFunction (out, scope->Function (j), ind, level);
282
num = scope->Children ();
284
indent (out, ind+2); out << num << " scopes:" << endl;
285
for (unsigned j = 0; j < num; j++) {
286
CStructure *info = scope->Child (j)->Structure ();
287
// if (info && info->Objects () &&
288
// ! (info->FunctionInfo () && ! info->FunctionInfo ()->isFctDef ())) {
289
DumpLocalScope (out, info, ind);
290
Dump (out, info, ind+4, level);
296
void CClassDatabase::DumpLocalScope (ostream &out, CObjectInfo *info, int ind) const {
298
if (info->Record () || info->NamespaceInfo () ||
299
info->FunctionInfo () || info->TemplateInfo ()) {
300
if (info->UnionInfo ())
302
else if (info->ClassInfo ())
303
out << (info->ClassInfo ()->isStruct () ? "struct" : "class");
304
else if (info->NamespaceInfo ())
306
else if (info->FunctionInfo ())
308
else if (info->TemplateInfo ())
310
out << " : " << info->Name ();
314
if (info->ClassInfo ()) {
315
unsigned base_classes = info->ClassInfo ()->BaseClasses ();
317
out << "[base classes: ";
318
for (unsigned i = 0; i < base_classes; i++) {
319
CClassInfo *cinfo = info->ClassInfo ()->BaseClass (i)->Class ();
320
if (cinfo && cinfo->TypeInfo ()) {
321
cinfo->TypeInfo ()->TypeText (out);
322
if (i+1 < base_classes)
329
DumpQualities (out, info);
333
void CClassDatabase::DumpFunction (ostream &out, CFunctionInfo *info, int ind, int level) const {
334
// CArgumentInfo* arg;
338
out << info->Name () << "\t (type: ";
339
info->TypeInfo ()->TypeText (out);
342
if (info->ObjectInfo()->QualifiedScope () && info->ObjectInfo()->QualifiedScope () != info->Scope ()) {
343
out << " [member of ";
344
DumpScopeName (out, info->ObjectInfo()->QualifiedScope ());
347
if (info->isDestructor ())
348
out << " [destructor]";
349
else if (info->isConstructor ())
350
out << " [constructor]";
351
if (! info->isDefined () && ! info->isBuiltin ())
352
out << " [undefined]";
353
if (info->isOperator () || info->isConversion ())
354
out << " [operator]";
356
DumpQualities (out, info);
362
// dump function arguments
363
// num = info->Arguments ();
365
// indent (out, ind+6); out << num << " arguments:" << endl;
366
// for (unsigned i = 0; i < num; i++) {
367
// arg = info->Argument (i);
368
// indent (out, ind+8); out << arg->Name () << "\t (type: ";
369
// arg->TypeInfo ()->TypeText (out);
371
// DumpQualities (out, arg);
377
void CClassDatabase::DumpAttribute (ostream &out, CAttributeInfo *info, int ind) const {
379
out << info->Name () << "\t (type: ";
380
info->TypeInfo ()->TypeText (out);
383
if (info->ObjectInfo()->QualifiedScope () && info->ObjectInfo()->QualifiedScope () != info->Scope ()) {
384
out << " [member of ";
385
DumpScopeName (out, info->ObjectInfo()->QualifiedScope ());
388
if (info->TypeInfo ()->isVarArray ())
389
out << " [dim: variable]";
390
else if ((info->TypeInfo ()->isArray () || info->TypeInfo ()->isBitField ()) &&
391
info->TypeInfo ()->Dimension () != -1)
392
out << " [dim: " << info->TypeInfo ()->Dimension () << "]";
393
else if (info->EnumeratorInfo ())
394
out << " [value: " << info->EnumeratorInfo ()->Value () << "]";
396
DumpQualities (out, info);
400
void CClassDatabase::DumpType (ostream &out, CObjectInfo *info, int ind) const {
402
if (info->TypedefInfo ())
404
else if (info->UnionInfo ())
406
else if (info->EnumInfo ())
408
else if (info->ClassInfo ())
409
out << (info->ClassInfo ()->isStruct () ? "struct " : "class ");
410
out << ": " << info->Name () << "\t";
411
if (info->EnumInfo ()) {
412
out << " (underlying type: ";
413
info->EnumInfo ()->TypeInfo ()->UnderlyingType ()->TypeText (out);
415
} else if (info->TypedefInfo ()) {
417
info->TypeInfo ()->TypeText (out);
419
} else if (info->ClassInfo ()) {
420
unsigned base_classes = info->ClassInfo ()->BaseClasses ();
422
out << "[base classes: ";
423
for (unsigned i = 0; i < base_classes; i++) {
424
CClassInfo *cinfo = info->ClassInfo ()->BaseClass (i)->Class ();
425
if (cinfo && cinfo->TypeInfo ()) {
426
cinfo->TypeInfo ()->TypeText (out);
427
if (i+1 < base_classes)
434
DumpQualities (out, info);
438
void CClassDatabase::DumpTemplateParam (ostream &out, CTemplateParamInfo *info, int ind) const {
440
out << info->Name () << "\t";
441
if (info->isTemplate ())
442
out << " [template] ";
443
else if (info->isTypeParam ())
446
out << " [non-type] ";
450
void CClassDatabase::DumpNamespace (ostream &out, CNamespaceInfo *info, int ind) const {
451
CNamespaceInfo *nsinfo;
453
out << "namespace : " << info->Name () << "\t";
454
if (info->isAlias ()) {
456
while (nsinfo->isAlias ()) {
457
nsinfo = (CNamespaceInfo*)nsinfo->NextObject ();
458
if (nsinfo == info) // should never be true
461
out << " [alias of ";
462
DumpScopeName (out, nsinfo);
465
DumpQualities (out, info);
469
void CClassDatabase::DumpUsing (ostream &out, CUsingInfo *info, int ind) const {
470
CNamespaceInfo *nsinfo = info->Namespace ();
472
out << "using namespace " << ": ";
473
DumpScopeName (out, nsinfo);
477
void CClassDatabase::DumpQualities (ostream &out, CObjectInfo *info) const {
478
if (info->isTemplate ())
479
out << " [template]";
480
if (info->TemplateInfo () && ! info->TemplateInfo ()->isBaseTemplate ())
481
out << " [specialization of " << (void*)info->TemplateInfo ()->BaseTemplate () << "]";
482
if (info->NamespaceInfo () && info->Name () && *info->Name ().c_str() == '%')
483
out << " [instance scope]";
484
if (info->isTemplateInstance ()) {
485
if (info->TemplateInstance ()->isPseudoInstance ())
486
out << " [pseudo instance]";
488
out << " [instance of "
489
<< (void*)info->TemplateInstance ()->Template () << "]";
492
// dump member access level
493
if (info->Protection () == CProtection::PROT_PROTECTED)
494
out << " [protected]";
495
else if (info->Protection () == CProtection::PROT_PRIVATE)
497
// else if (info->Protection () == CProtection::PROT_PUBLIC)
498
// out << " [public]";
501
if (! (info->Language () == CLanguage::LANG_UNDEFINED))
502
out << " [language: " << info->Language ().Text () << "]";
504
// dump type qualities
505
if (info->TypeInfo () && info->TypeInfo ()->isVolatile ())
506
out << " [volatile]";
507
if (info->TypeInfo () && info->TypeInfo ()->isConst ())
510
if (info->isBuiltin ())
512
if (info->isInline ())
514
if (info->isAnonymous ())
515
out << " [anonymous]";
517
if (info->isVirtual ())
519
if (info->isStatic ())
521
if (info->isExtern ())
523
if (info->isMutable ())
525
if (info->isRegister ())
526
out << " [register]";
528
// dump storage class
529
if (info->Storage () == CStorage::CLASS_DYNAMIC)
531
// else if (info->Storage () == CStorage::CLASS_STATIC)
532
// out << " [static]";
533
// else if (info->Storage () == CStorage::CLASS_AUTOMATIC)
534
// out << " [automatic]";
537
out << " [" << (void*)info << "]";
538
// dump next linked object
539
if (info->NextObject () != info)
540
out << " [next: " << (void*)info->NextObject () << "]";
543
void CClassDatabase::DumpScopeName (ostream &out, CStructure *scope) const {
544
if (scope->FileInfo ())
547
CStructure *parent = scope->Parent ()->Structure ();
548
if (parent->isRecord () || parent->isNamespace ()) {
549
DumpScopeName (out, parent);
550
out << "::" << scope->Name ();
552
out << scope->Name ();
555
void CClassDatabase::indent (ostream &out, int ind) const {
556
for (int i = 0; i < ind; i++)