Newer
Older
/* /% C++ %/ */
/***********************************************************************
* cint (C/C++ interpreter)
************************************************************************
* Source file DataMbr.cxx
************************************************************************
* Description:
* Extended Run Time Type Identification API
************************************************************************
* Author Masaharu Goto
* Copyright(c) 1995~2004 Masaharu Goto
*
* For the licensing terms see the file COPYING
*
************************************************************************/
#include "Api.h"
#include "Dict.h"
#include "common.h"
#include "fproto.h"
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <string>
#include <vector>
using namespace std;
using namespace Cint::Internal;
// File static functions.
static Cint::G__DataMemberInfo GetDataMemberFromAll(G__ClassInfo& cl, const char* varname);
static int IsInt(G__DataMemberInfo& member);
static Cint::G__DataMemberInfo GetDataMemberFromAllParents(G__ClassInfo& cl, const char* varname);
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//______________________________________________________________________________
//
// Static functions.
//
//______________________________________________________________________________
static Cint::G__DataMemberInfo GetDataMemberFromAll(G__ClassInfo& cl, const char* varname)
{
// Find the data member whose name exactly match varname
// If this is 'augmented' to be able to interpret specified variable name
// (for example *fN)
// the function IsInt need to be changed to take that in consideration.
G__DataMemberInfo member(cl);
while (member.Next()) {
if (!strcmp(varname, member.Name())) {
return member;
}
}
// after the last Next member is now invalid.
return member;
}
//______________________________________________________________________________
static int IsInt(G__DataMemberInfo& member)
{
int type = member.Type()->Type();
if (member.Property() & G__BIT_ISARRAY) {
return 0;
}
switch (type) {
// -- A lower case indicated that it is NOT a pointer to that type.
case 'b': // unsigned char
case 'c': // char
case 'r': // unsigned short
case 's': // short
case 'h': // unsigned int
case 'i': // int
case 'k': // unsigned long
case 'l': // long
return 1;
break;
}
return 0;
}
//______________________________________________________________________________
static Cint::G__DataMemberInfo GetDataMemberFromAllParents(G__ClassInfo& cl, const char* varname)
{
//
// Recurse through all the bases classes to find a
// data member.
//
G__DataMemberInfo index;
G__BaseClassInfo b(cl);
while (b.Next()) {
index = GetDataMemberFromAll(b, varname);
if (index.IsValid()) {
return index;
}
index = GetDataMemberFromAllParents(b, varname);
if (index.IsValid()) {
return index;
}
}
return G__DataMemberInfo();
}
//______________________________________________________________________________
//
// Class Member Functions.
//
//______________________________________________________________________________
Cint::G__DataMemberInfo::~G__DataMemberInfo()
{
delete m_memberof;
delete m_typeinfo;
}
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//______________________________________________________________________________
Cint::G__DataMemberInfo::G__DataMemberInfo()
: m_memberiter(-1)
, m_typeinfo(0) // we own, cache object
, m_memberof(0) // we own, cache object
{
}
//______________________________________________________________________________
Cint::G__DataMemberInfo::G__DataMemberInfo(class G__ClassInfo& class_info)
: m_memberiter(-1)
, m_typeinfo(0) // we own, cache object
, m_memberof(0) // we own, cache object
{
Init(class_info);
}
//______________________________________________________________________________
Cint::G__DataMemberInfo::G__DataMemberInfo(const ::Reflex::Member mbr)
: m_scope(mbr.DeclaringScope())
, m_datambr(mbr)
, m_memberiter(-1)
, m_typeinfo(0) // we own, cache object
, m_memberof(0) // we own, cache object
{
}
//______________________________________________________________________________
Cint::G__DataMemberInfo::G__DataMemberInfo(const G__DataMemberInfo& rhs)
: m_scope(rhs.m_scope)
, m_datambr(rhs.m_datambr)
, m_memberiter(rhs.m_memberiter)
, m_typeinfo(0) // we own, cache object
, m_memberof(0) // we own, cache object
{
}
//______________________________________________________________________________
G__DataMemberInfo& Cint::G__DataMemberInfo::operator=(const G__DataMemberInfo& rhs)
{
if (this != &rhs) {
m_scope = rhs.m_scope;
m_datambr = rhs.m_datambr;
m_memberiter = rhs.m_memberiter;
delete m_typeinfo; // we own, cache object
m_typeinfo = 0; // we own, cache object
delete m_memberof; // we own, cache object
m_memberof = 0; // we own, cache object
}
return *this;
}
//______________________________________________________________________________
void Cint::G__DataMemberInfo::Init()
{
m_scope = ::Reflex::Scope();
m_datambr = ::Reflex::Member();
delete m_typeinfo;
m_typeinfo = 0; // we own, cache object
delete m_memberof;
m_memberof = 0; // we own, cache object
}
//______________________________________________________________________________
void Cint::G__DataMemberInfo::Init(class G__ClassInfo& a)
{
if (a.IsValid()) {
m_scope = a.ReflexType();
m_datambr = ::Reflex::Member();
m_memberiter = -1;
delete m_typeinfo; // we own, cache object
m_typeinfo = 0; // we own, cache object
delete m_memberof; // we own, cache object
m_memberof = 0; // we own, cache object
G__incsetup_memvar((int) a.Tagnum());
}
else {
m_scope = ::Reflex::Scope();
m_datambr = ::Reflex::Member();
m_memberiter = -1;
delete m_typeinfo; // we own, cache object
m_typeinfo = 0; // we own, cache object
delete m_memberof; // we own, cache object
m_memberof = 0; // we own, cache object
}
}
//______________________________________________________________________________
void Cint::G__DataMemberInfo::Init(const ::Reflex::Scope a)
m_memberiter = -1;
delete m_typeinfo; // we own, cache object
m_typeinfo = 0; // we own, cache object
delete m_memberof; // we own, cache object
m_memberof = 0; // we own, cache object
if (!a) {
m_scope = ::Reflex::Scope();
m_datambr = ::Reflex::Member();
}
else {
m_datambr = ::Reflex::Member();
G__incsetup_memvar(G__get_tagnum(a));
}
}
//______________________________________________________________________________
void Cint::G__DataMemberInfo::Init(long handlein, long indexin, G__ClassInfo* belongingclassin)
{
if (handlein) {
m_memberiter = -1;
delete m_typeinfo; // we own, cache object
m_typeinfo = 0; // we own, cache object
m_datambr = G__Dict::GetDict().GetDataMember(handlein);
delete m_memberof; // we own, cache object
m_memberof = 0; // we own, cache object
if (belongingclassin && belongingclassin->IsValid()) {
m_scope = belongingclassin->ReflexType();
}
else {
m_scope = ::Reflex::Scope();
}
}
else {
m_memberiter = -1;
delete m_typeinfo; // we own, cache object
m_typeinfo = 0; // we own, cache object
m_datambr = ::Reflex::Member();
//______________________________________________________________________________
size_t Cint::G__DataMemberInfo::Handle()
{
return (size_t) m_datambr.Id();
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::Index()
{
return 0;
}
//______________________________________________________________________________
const char* Cint::G__DataMemberInfo::Name()
{
if (!IsValid()) {
return 0;
return m_datambr.Name().c_str();
}
//______________________________________________________________________________
const char* Cint::G__DataMemberInfo::Title()
{
static char buf[G__INFO_TITLELEN];
buf[0] = '\0';
if (IsValid()) {
G__getcomment(buf, &G__get_properties(m_datambr)->comment, G__get_tagnum(m_scope));
return buf;
}
return 0;
}
//______________________________________________________________________________
::Reflex::Type Cint::G__DataMemberInfo::ReflexType()
{
// Return the data member type as a Reflex Type object.
return m_datambr.TypeOf();
}
//______________________________________________________________________________
G__TypeInfo* Cint::G__DataMemberInfo::Type()
{
// Return the data member type as a Cint TypeInfo object.
// Note this is slow use ReflexType instead.
if (m_typeinfo) {
return m_typeinfo;
}
m_typeinfo = new G__TypeInfo(m_datambr.TypeOf());
return m_typeinfo;
}
//______________________________________________________________________________
long Cint::G__DataMemberInfo::Property()
{
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
if (!IsValid()) {
return 0;
}
long property = 0;
switch (G__get_access(m_datambr)) {
case G__PUBLIC:
property |= G__BIT_ISPUBLIC;
break;
case G__PROTECTED:
property |= G__BIT_ISPROTECTED;
break;
case G__PRIVATE:
property |= G__BIT_ISPRIVATE;
break;
}
if (G__test_static(m_datambr, G__LOCALSTATIC)) {
property |= G__BIT_ISSTATIC;
}
if (m_datambr.TypeOf().FinalType().IsReference()) {
property |= G__BIT_ISREFERENCE;
}
if (isupper(G__get_type(m_datambr.TypeOf()))) {
property |= G__BIT_ISPOINTER;
}
if (G__test_const(m_datambr, G__CONSTVAR)) {
property |= G__BIT_ISCONSTANT;
}
if (G__test_const(m_datambr, G__PCONSTVAR)) {
property |= G__BIT_ISPCONSTANT;
}
if (G__get_paran(m_datambr)) {
property |= G__BIT_ISARRAY;
}
if (m_datambr.TypeOf().IsTypedef()) {
property |= G__BIT_ISTYPEDEF;
}
if (m_datambr.TypeOf().RawType().IsFundamental()) {
property |= G__BIT_ISFUNDAMENTAL;
}
else {
std::string cname(m_datambr.TypeOf().RawType().Name());
if ((cname == "G__longlong") || (cname == "G__ulonglong") || (cname == "G__longdouble")) {
property |= G__BIT_ISFUNDAMENTAL;
cname = m_datambr.TypeOf().FinalType().Name(Reflex::FINAL);
if (
(property & G__BIT_ISTYPEDEF) &&
((cname == "long long") || (cname == "unsigned long long") || (cname == "long double"))
) {
property &= (~G__BIT_ISTYPEDEF);
}
switch (G__get_tagtype(m_datambr.TypeOf().RawType())) {
case 'c':
property |= G__BIT_ISCLASS;
break;
case 'e':
property |= G__BIT_ISENUM;
break;
case 'n':
property |= G__BIT_ISNAMESPACE;
break;
case 's':
property |= G__BIT_ISSTRUCT;
break;
case 'u':
property |= G__BIT_ISUNION;
break;
return property;
}
//______________________________________________________________________________
long Cint::G__DataMemberInfo::Offset()
{
if (!IsValid()) {
return -1;
return (long) G__get_properties(m_datambr)->addressOffset;
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::Bitfield()
{
if (!IsValid()) {
return -1;
return G__get_bitfield_width(m_datambr);
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::ArrayDim()
{
if (!IsValid()) {
return -1;
return G__get_paran(m_datambr);
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::MaxIndex(int dim)
{
if (!IsValid() || (dim < 0) || (dim >= G__get_paran(m_datambr))) {
return -1;
if (dim) {
// -- Stored directly for second and greater dimensions.
return G__get_varlabel(m_datambr, dim + 1);
}
// -- For first dimension divide number of elements by stride.
// Note: This may be zero, if this is not an array!
return G__get_varlabel(m_datambr, 1) /* num of elements */ / G__get_varlabel(m_datambr, 0) /* stride */;
}
//______________________________________________________________________________
::Reflex::Scope Cint::G__DataMemberInfo::DeclaringScope()
{
// Return the scope to which the member belongs.
return m_scope;
}
//______________________________________________________________________________
G__ClassInfo* Cint::G__DataMemberInfo::MemberOf()
{
// Return the scope to which the member belongs as a legacy Cint object.
// Note: this is slow use DeclaringScope instead.
delete m_memberof;
m_memberof = new G__ClassInfo(m_scope.Name(::Reflex::SCOPED).c_str());
return m_memberof;
}
//______________________________________________________________________________
void Cint::G__DataMemberInfo::SetGlobalcomp(int globalcomp)
{
if (IsValid()) {
G__get_properties(m_datambr)->globalcomp = globalcomp;
}
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::IsValid()
{
bool valid = m_datambr;
return valid;
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::SetFilePos(const char* fname)
{
struct G__dictposition* dict = G__get_dictpos((char*) fname);
if (!dict) {
return 0;
}
delete m_typeinfo;
m_typeinfo = 0;
delete m_memberof;
m_memberof = 0;
m_scope = dict->var;
m_memberiter = dict->ig15 - 1;
m_datambr = m_scope.DataMemberAt(m_memberiter);
return 1;
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::Next()
{
if (!m_scope) {
return 0;
++m_memberiter;
delete m_typeinfo;
m_typeinfo = 0;
if (m_memberiter < (int) m_scope.DataMemberSize()) {
m_datambr = m_scope.DataMemberAt(m_memberiter);
} else {
m_memberiter = -1;
m_datambr = ::Reflex::Member();
}
return (bool) m_datambr;
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::Prev()
{
if (!m_scope) {
return 0;
delete m_typeinfo;
m_typeinfo = 0;
if (m_memberiter == -1) {
m_memberiter = m_scope.DataMemberSize();
--m_memberiter;
if (m_memberiter < 0) {
m_datambr = ::Reflex::Member();
return 0;
m_datambr = m_scope.DataMemberAt(m_memberiter);
return 1;
}
//______________________________________________________________________________
const char* Cint::G__DataMemberInfo::ValidArrayIndex(int* errnum /*= 0*/, char** errstr /*= 0*/)
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
{
// ValidArrayIndex return a static string (so use it or copy it immediatly, do not
// call GrabIndex twice in the same expression) containing the size of the
// array data member.
// In case of error, or if the size is not specified, GrabIndex returns 0.
// If errnum is not null, *errnum updated with the error number:
// Cint::G__DataMemberInfo::G__VALID : valid array index
// Cint::G__DataMemberInfo::G__NOT_INT : array index is not an int
// Cint::G__DataMemberInfo::G__NOT_DEF : index not defined before array
// (this IS an error for streaming to disk)
// Cint::G__DataMemberInfo::G__IS_PRIVATE: index exist in a parent class but is private
// Cint::G__DataMemberInfo::G__UNKNOWN : index is not known
// If errstr is not null, *errstr is updated with the address of a static
// string containing the part of the index with is invalid.
const char* title = 0;
//long dummy;
// Let's see if the user provided us with some information
// with the format: //[dimension] this is the dim of the array
// dimension can be an arithmetical expression containing, literal integer,
// the operator *,+ and - and data member of integral type. In addition the
// data members used for the size of the array need to be defined prior to
// the array.
if (errnum) {
*errnum = VALID;
}
title = Title();
if (strncmp(title, "[", 1) || !strstr(title, "]")) {
return 0;
}
// FIXME: This is not thread safe!
static char working[G__INFO_TITLELEN];
static char indexvar[G__INFO_TITLELEN];
strcpy(indexvar, title + 1);
strstr(indexvar, "]")[0] = '\0';
// now we should have indexvar=dimension
// Let's see if this is legal.
// which means a combination of data member and digit separated by '*','+','-'
// First we remove white spaces.
unsigned int i = 0;
unsigned int j = 0;
for (; i <= strlen(indexvar); ++i) {
if (!isspace(indexvar[i])) {
working[j++] = indexvar[i];
}
};
// Now we go through all indentifiers
const char* tokenlist = "*+-";
char* current = working;
current = strtok(current, tokenlist);
G__ClassInfo belongingclass(G__get_tagnum(m_scope));
while (current) {
// Check the token
if (isdigit(current[0])) {
for(i = 0; i <strlen(current); ++i) {
if (!isdigit(current[0])) {
// Error we only access integer.
//NOTE: *** Need to print an error;
//fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not an interger\n",
// member.MemberOf()->Name(), member.Name(), current);
if (errstr) {
*errstr = current;
}
if (errnum) {
*errnum = NOT_INT;
}
return 0;
}
}
} else {
// current token is not a digit
// first let's see if it is a data member:
int found = 0;
G__DataMemberInfo index1 = GetDataMemberFromAll(belongingclass, current );
if (index1.IsValid()) {
if (IsInt(index1)) {
found = 1;
// Let's see if it has already been wrote down in the
// Streamer.
// Let's see if we already wrote it down in the
// streamer.
G__DataMemberInfo m_local(belongingclass);
while (m_local.Next()) {
if (!strcmp(m_local.Name(), Name())) {
// we reached the current data member before
// reaching the index so we have not wrote it yet!
//NOTE: *** Need to print an error;
//fprintf(stderr,"*** Datamember %s::%s: size of array (%s) has not been defined before the array \n",
// member.MemberOf()->Name(), member.Name(), current);
if (errstr) {
*errstr = current;
}
if (errnum) {
*errnum = NOT_DEF;
}
return 0;
}
if (!strcmp(m_local.Name(), current)) {
break;
}
} // end of while (m_local.Next())
} else {
//NOTE: *** Need to print an error;
//fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not int \n",
// member.MemberOf()->Name(), member.Name(), current);
if (errstr) {
*errstr = current;
}
if (errnum) {
*errnum = NOT_INT;
}
return 0;
}
} else {
// There is no variable by this name in this class, let see
// the base classes!
index1 = GetDataMemberFromAllParents(belongingclass, current);
if (index1.IsValid()) {
if (IsInt(index1)) {
found = 1;
} else {
// We found a data member but it is the wrong type
//NOTE: *** Need to print an error;
//fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not int \n",
// member.MemberOf()->Name(), member.Name(), current);
if (errnum) {
*errnum = NOT_INT;
}
if (errstr) {
*errstr = current;
}
return 0;
}
if (found && (index1.Property() & G__BIT_ISPRIVATE)) {
//NOTE: *** Need to print an error;
//fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is a private member of %s \n",
if (errstr) {
*errstr = current;
}
if (errnum) {
*errnum = IS_PRIVATE;
}
return 0;
}
}
if (!found) {
//NOTE: *** Need to print an error;
//fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not known \n",
// member.MemberOf()->Name(), member.Name(), indexvar);
if (errstr) {
*errstr = indexvar;
}
if (errnum) {
*errnum = UNKNOWN;
}
return 0;
} // end of if not found
} // end of if is a data member of the class
} // end of if isdigit
current = strtok(0, tokenlist);
} // end of while loop on tokens
return indexvar;
}
//______________________________________________________________________________
const char* Cint::G__DataMemberInfo::FileName()
// --
#ifdef G__VARIABLEFPOS
if (!IsValid()) {
if (G__get_properties(m_datambr)->filenum >= 0) {
return G__srcfile[G__get_properties(m_datambr)->filenum].filename;
return "(compiled)";
#else // G__VARIABLEFPOS
G__fprinterr("Warning: Cint::G__DataMemberInfo::Filename() not supported in this configuration. define G__VARIABLEFPOS macro in platform dependency file and recompile cint");
G__printlinenum();
#endif // G__VARIABLEFPOS
// --
}
//______________________________________________________________________________
int Cint::G__DataMemberInfo::LineNumber()
// --
#ifdef G__VARIABLEFPOS
if (!IsValid()) {
return -1;
if (G__get_properties(m_datambr)->filenum >= 0) { // interpreted code
return G__get_properties(m_datambr)->linenum;
}
return -1; // compiled code
#else // G__VARIABLEFPOS
G__fprinterr("Warning: Cint::G__DataMemberInfo::LineNumber() not supported in this configuration. define G__VARIABLEFPOS macro in platform dependency file and recompile cint");
G__printlinenum();
return -1;
#endif // G__VARIABLEFPOS
// --