00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "typeinfo.h"
00016 #include "encoding.h"
00017 #include "ptree-core.h"
00018 #include "env.h"
00019 #include "mop.h"
00020
00021 TypeInfo::TypeInfo()
00022 {
00023 refcount = 0;
00024 encode = nil;
00025 metaobject = nil;
00026 env = nil;
00027 }
00028
00029 void TypeInfo::Unknown()
00030 {
00031 refcount = 0;
00032 encode = nil;
00033 metaobject = nil;
00034 env = nil;
00035 }
00036
00037 void TypeInfo::Set(char* type, Environment* e)
00038 {
00039 refcount = 0;
00040 encode = type;
00041 metaobject = nil;
00042 env = e;
00043 }
00044
00045 void TypeInfo::Set(Class* m)
00046 {
00047 refcount = 0;
00048 encode = nil;
00049 metaobject = m;
00050 env = nil;
00051 }
00052
00053 void TypeInfo::SetVoid()
00054 {
00055 refcount = 0;
00056 encode = "v";
00057 metaobject = nil;
00058 env = nil;
00059 }
00060
00061 void TypeInfo::SetInt()
00062 {
00063 refcount = 0;
00064 encode = "i";
00065 metaobject = nil;
00066 env = nil;
00067 }
00068
00069 void TypeInfo::SetMember(Ptree* member)
00070 {
00071 Class* c = ClassMetaobject();
00072 if(c == nil)
00073 Unknown();
00074 else{
00075 Environment* e = c->GetEnvironment();
00076 if(e == nil)
00077 Unknown();
00078 else
00079 e->Lookup(member, *this);
00080 }
00081 }
00082
00083 TypeInfoId TypeInfo::WhatIs()
00084 {
00085 if(refcount > 0)
00086 return PointerType;
00087
00088 Normalize();
00089 if(metaobject != nil)
00090 return ClassType;
00091
00092 Environment* e = env;
00093 char* ptr = SkipCv(encode, e);
00094 if(ptr == nil)
00095 return UndefType;
00096
00097 switch(*ptr){
00098 case 'T' :
00099 return TemplateType;
00100 case 'P' :
00101 return PointerType;
00102 case 'R' :
00103 return ReferenceType;
00104 case 'M' :
00105 return PointerToMemberType;
00106 case 'A' :
00107 return ArrayType;
00108 case 'F' :
00109 return FunctionType;
00110 case 'S' : case 'U' :
00111 case 'b' : case 'c' : case 'i' : case 's' : case 'l' : case 'j' :
00112 case 'f' : case 'd' : case 'r' : case 'v' :
00113 return BuiltInType;
00114 default :
00115 if(*ptr == 'Q' || *(unsigned char*)ptr >= 0x80){
00116 TypeInfo t;
00117 Class* c;
00118 t.Set(ptr, e);
00119 if(t.IsClass(c))
00120 return ClassType;
00121 else if(t.IsEnum())
00122 return EnumType;
00123 }
00124
00125 return UndefType;
00126 };
00127 }
00128
00129 bool TypeInfo::IsNoReturnType()
00130 {
00131 Normalize();
00132 Environment* e = env;
00133 char* ptr = SkipCv(encode, e);
00134 return(ptr != nil && *ptr == '?');
00135 }
00136
00137 bool TypeInfo::IsConst()
00138 {
00139 Normalize();
00140 char* ptr = encode;
00141 return(ptr != nil && *ptr == 'C');
00142 }
00143
00144 bool TypeInfo::IsVolatile()
00145 {
00146 Normalize();
00147 char* ptr = encode;
00148 if(ptr == nil)
00149 return FALSE;
00150 else if(*ptr == 'V')
00151 return TRUE;
00152 else if(*ptr == 'C')
00153 return(ptr[1] == 'V');
00154 else
00155 return FALSE;
00156 }
00157
00158 uint TypeInfo::IsBuiltInType()
00159 {
00160 Normalize();
00161 Environment* e = env;
00162 char* ptr = SkipCv(encode, e);
00163 if(ptr == nil)
00164 return 0;
00165
00166 uint result = 0;
00167 for(;; ++ptr){
00168 switch(*ptr){
00169 case 'b' :
00170 return(result | BooleanType);
00171 case 'c' :
00172 return(result | CharType);
00173 case 'i' :
00174 return(result | IntType);
00175 case 's' :
00176 return(result | ShortType);
00177 case 'l' :
00178 return(result | LongType);
00179 case 'j' :
00180 return(result | LongLongType);
00181 case 'f' :
00182 return(result | FloatType);
00183 case 'd' :
00184 return(result | DoubleType);
00185 case 'r' :
00186 return(result | LongDoubleType);
00187 case 'v' :
00188 return(result | VoidType);
00189 case 'S' :
00190 result |= SignedType;
00191 break;
00192 case 'U' :
00193 result |= UnsignedType;
00194 break;
00195 default :
00196 return 0;
00197 }
00198 }
00199 }
00200
00201 bool TypeInfo::IsFunction()
00202 {
00203 Normalize();
00204 Environment* e = env;
00205 char* ptr = SkipCv(encode, e);
00206 return(ptr != nil && *ptr == 'F');
00207 }
00208
00209 bool TypeInfo::IsEllipsis()
00210 {
00211 Normalize();
00212 Environment* e = env;
00213 char* ptr = SkipCv(encode, e);
00214 return(ptr != nil && *ptr == 'e');
00215 }
00216
00217 bool TypeInfo::IsPointerType()
00218 {
00219 if(refcount > 0)
00220 return TRUE;
00221
00222 Normalize();
00223 Environment* e = env;
00224 char* ptr = SkipCv(encode, e);
00225 if(ptr != nil){
00226 char c = *ptr;
00227 return c == 'P' || c == 'A' || c == 'M';
00228 }
00229
00230 return FALSE;
00231 }
00232
00233 bool TypeInfo::IsReferenceType()
00234 {
00235 Normalize();
00236 Environment* e = env;
00237 char* ptr = SkipCv(encode, e);
00238 return(ptr != nil && *ptr == 'R');
00239 }
00240
00241 bool TypeInfo::IsArray()
00242 {
00243 Normalize();
00244 Environment* e = env;
00245 char* ptr = SkipCv(encode, e);
00246 return(ptr != nil && *ptr == 'A');
00247 }
00248
00249 bool TypeInfo::IsPointerToMember()
00250 {
00251 Normalize();
00252 Environment* e = env;
00253 char* ptr = SkipCv(encode, e);
00254 return(ptr != nil && *ptr == 'M');
00255 }
00256
00257 bool TypeInfo::IsTemplateClass()
00258 {
00259 Normalize();
00260 Environment* e = env;
00261 char* ptr = SkipCv(encode, e);
00262 return(ptr != nil && *ptr == 'T');
00263 }
00264
00265 Class* TypeInfo::ClassMetaobject()
00266 {
00267 Class* c;
00268 IsClass(c);
00269 return c;
00270 }
00271
00272 bool TypeInfo::IsClass(Class*& c)
00273 {
00274 Normalize();
00275 if(metaobject != nil){
00276 c = metaobject;
00277 return TRUE;
00278 }
00279 else{
00280 c = nil;
00281 Environment* e = env;
00282 char* encode2 = SkipCv(encode, e);
00283 if(encode == encode2)
00284 return FALSE;
00285
00286 TypeInfo tinfo;
00287 tinfo.Set(encode2, e);
00288 return tinfo.IsClass(c);
00289 }
00290 }
00291
00292 bool TypeInfo::IsEnum()
00293 {
00294 Ptree* spec;
00295 return IsEnum(spec);
00296 }
00297
00298 bool TypeInfo::IsEnum(Ptree*& spec)
00299 {
00300 spec = nil;
00301 Normalize();
00302 if(metaobject != nil)
00303 return FALSE;
00304 else{
00305 Bind* bind;
00306 int len;
00307 Environment* e = env;
00308 char* name = Encoding::GetBaseName(encode, len, e);
00309 if(name != nil && e != nil)
00310 if(e->LookupType(name, len, bind))
00311 if(bind != nil && bind->What() == Bind::isEnumName){
00312 spec = ((BindEnumName*)bind)->GetSpecification();
00313 return TRUE;
00314 }
00315
00316 e = env;
00317 name = SkipCv(encode, e);
00318 if(name == encode)
00319 return FALSE;
00320
00321 TypeInfo tinfo;
00322 tinfo.Set(name, e);
00323 return tinfo.IsEnum(spec);
00324 }
00325 }
00326
00327 void TypeInfo::Dereference(TypeInfo& t)
00328 {
00329 t.refcount = refcount - 1;
00330 t.encode = encode;
00331 t.metaobject = metaobject;
00332 t.env = env;
00333 }
00334
00335 void TypeInfo::Reference(TypeInfo& t)
00336 {
00337 t.refcount = refcount + 1;
00338 t.encode = encode;
00339 t.metaobject = metaobject;
00340 t.env = env;
00341 }
00342
00343 bool TypeInfo::NthArgument(int n, TypeInfo& t)
00344 {
00345 Environment* e = env;
00346 Normalize();
00347 char* ptr = SkipCv(encode, e);
00348 if(ptr == nil || *ptr != 'F'){
00349 t.Unknown();
00350 return FALSE;
00351 }
00352
00353 ++ptr;
00354 if(*ptr == 'v'){
00355 t.SetVoid();
00356 return FALSE;
00357 }
00358
00359 while(n-- > 0){
00360 ptr = SkipType(ptr, e);
00361 if(ptr == nil || *ptr == '_'){
00362 t.Unknown();
00363 return FALSE;
00364 }
00365 }
00366
00367 t.Set(ptr, e);
00368 return TRUE;
00369 }
00370
00371 int TypeInfo::NumOfArguments()
00372 {
00373 Environment* e = env;
00374 Normalize();
00375 char* ptr = SkipCv(encode, e);
00376 if(ptr == nil || *ptr != 'F')
00377 return -1;
00378
00379 ++ptr;
00380 if(*ptr == 'v')
00381 return 0;
00382
00383 int n = 0;
00384 for(;;){
00385 ++n;
00386 ptr = SkipType(ptr, e);
00387 if(ptr == nil || *ptr == '_')
00388 return n;
00389 }
00390 }
00391
00392 bool TypeInfo::NthTemplateArgument(int n, TypeInfo& t)
00393 {
00394 Environment* e = env;
00395 Normalize();
00396 char* ptr = SkipCv(encode, e);
00397 if(ptr == nil || *ptr != 'T'){
00398 t.Unknown();
00399 return FALSE;
00400 }
00401
00402 int len;
00403 ptr = (char*)Encoding::GetTemplateArguments((unsigned char*)++ptr, len);
00404 char* end = ptr + len;
00405 while(n-- > 0){
00406 ptr = SkipType(ptr, e);
00407 if(ptr == nil || ptr >= end) {
00408 t.Unknown();
00409 return FALSE;
00410 }
00411 }
00412
00413 t.Set(ptr, e);
00414 return TRUE;
00415 }
00416
00417 Ptree* TypeInfo::FullTypeName()
00418 {
00419 Ptree *qname, *head;
00420
00421 Normalize();
00422 if(metaobject != nil){
00423 qname = metaobject->Name();
00424 head = GetQualifiedName2(metaobject);
00425 if(head == nil)
00426 return qname;
00427 else
00428 return Ptree::Snoc(head, qname);
00429 }
00430
00431 Environment* e = env;
00432 unsigned char* name = (unsigned char*)SkipCv(encode, e);
00433 if(name == nil)
00434 return nil;
00435
00436 if(IsBuiltInType())
00437 return Encoding::MakePtree(name, nil)->First();
00438
00439 if(*name == 'T'){
00440 ++name;
00441 qname = Encoding::MakeLeaf(name);
00442 head = GetQualifiedName(e, qname);
00443 if(head == nil)
00444 return qname;
00445 else
00446 return Ptree::Snoc(head, qname);
00447 }
00448 else if(*name == 'Q'){
00449 qname = Encoding::MakeQname(++name);
00450 head = GetQualifiedName(e, qname->Car());
00451 if(head == nil)
00452 return qname;
00453 else
00454 return Ptree::Nconc(head, qname);
00455 }
00456 else if(Encoding::IsSimpleName(name)){
00457 qname = Encoding::MakeLeaf(name);
00458 head = GetQualifiedName(e, qname);
00459 if(head == nil)
00460 return qname;
00461 else
00462 return Ptree::Snoc(head, qname);
00463 }
00464 else
00465 return nil;
00466 }
00467
00468 Ptree* TypeInfo::GetQualifiedName(Environment* e, Ptree* tname)
00469 {
00470 Class* c = e->LookupClassMetaobject(tname);
00471 if(c == nil)
00472 return nil;
00473 else
00474 return GetQualifiedName2(c);
00475 }
00476
00477 Ptree* TypeInfo::GetQualifiedName2(Class* c)
00478 {
00479 Ptree* qname = nil;
00480 Environment* e = c->GetEnvironment();
00481 if(e != nil)
00482 e = e->GetOuterEnvironment();
00483
00484 for(; e != nil; e = e->GetOuterEnvironment()){
00485 c = e->IsClassEnvironment();
00486 if(c != nil)
00487 qname = Ptree::Cons(c->Name(),
00488 Ptree::Cons(Encoding::scope, qname));
00489 }
00490
00491 return qname;
00492 }
00493
00494 Ptree* TypeInfo::MakePtree(Ptree* name)
00495 {
00496 Normalize();
00497 if(metaobject != nil){
00498 Ptree* decl;
00499 if(name == nil)
00500 decl = nil;
00501 else
00502 decl = Ptree::List(name);
00503
00504 return Ptree::List(FullTypeName(), decl);
00505 }
00506 else if(encode != nil){
00507 unsigned char* ptr = (unsigned char*)encode;
00508 return Encoding::MakePtree(ptr, name);
00509 }
00510 else
00511 return nil;
00512 }
00513
00514 void TypeInfo::Normalize()
00515 {
00516 Environment* e = env;
00517 char* ptr = encode;
00518 int r = refcount;
00519
00520 if(ptr == nil)
00521 return;
00522 else if(r > 0)
00523 return;
00524
00525 while(r < 0)
00526 switch(*ptr){
00527 case 'C' :
00528 case 'V' :
00529 ++ptr;
00530 break;
00531 case 'A' :
00532 case 'P' :
00533 case 'R' :
00534 ++ptr;
00535 ++r;
00536 break;
00537 case 'F' :
00538 case 'M' :
00539 {
00540 char* p;
00541 if(*ptr == 'F')
00542 p = GetReturnType(ptr + 1, e);
00543 else
00544 p = SkipName(ptr + 1, e);
00545
00546 if(p == nil)
00547 return;
00548 else{
00549 ptr = p;
00550 ++r;
00551 }
00552 break;
00553 }
00554 default :
00555 if(!ResolveTypedef(e, ptr, TRUE))
00556 return;
00557 }
00558
00559 while(ResolveTypedef(e, ptr, FALSE))
00560 ;
00561 }
00562
00563 bool TypeInfo::ResolveTypedef(Environment*& e, char*& ptr, bool resolvable)
00564 {
00565 Bind* bind;
00566 int len;
00567 Class* c;
00568 Environment* orig_e = e;
00569 char* name = Encoding::GetBaseName(ptr, len, e);
00570 if(name != nil && e != nil && e->LookupType(name, len, bind))
00571 switch(bind->What()){
00572 case Bind::isTypedefName :
00573 ptr = bind->GetEncodedType();
00574 return TRUE;
00575 case Bind::isClassName :
00576 c = bind->ClassMetaobject();
00577 if(c == nil)
00578 Set(ptr, orig_e);
00579 else if (*name == 'T')
00580 Set(ptr, c->GetEnvironment());
00581 else
00582 Set(c);
00583
00584 return FALSE;
00585 case Bind::isTemplateClass :
00586 c = bind->ClassMetaobject();
00587 if(c == nil)
00588 Set(ptr, orig_e);
00589 else
00590 Set(ptr, c->GetEnvironment());
00591
00592 return FALSE;
00593 default :
00594 break;
00595 }
00596
00597 if(resolvable)
00598 Unknown();
00599 else
00600 Set(ptr, orig_e);
00601
00602 return FALSE;
00603 }
00604
00605 char* TypeInfo::SkipCv(char* ptr, Environment*& e)
00606 {
00607 if(ptr == nil)
00608 return nil;
00609
00610 for(;;)
00611 switch(*ptr){
00612 case 'C' :
00613 case 'V' :
00614 ++ptr;
00615 break;
00616 default :
00617 goto finish;
00618 }
00619
00620 finish:
00621 for(;;){
00622 Bind* bind;
00623 int len;
00624 char* name = Encoding::GetBaseName(ptr, len, e);
00625 if(name != nil && e != nil && e->LookupType(name, len, bind))
00626 if(bind->What() != Bind::isTypedefName)
00627 return ptr;
00628 else
00629 ptr = bind->GetEncodedType();
00630 else
00631 return ptr;
00632 }
00633 }
00634
00635 char* TypeInfo::SkipName(char* encode, Environment* e)
00636 {
00637 if(e == nil)
00638 MopErrorMessage("TypeInfo::SkipName()", "nil environment");
00639
00640 int len;
00641 Environment* e2 = e;
00642 char* ptr = Encoding::GetBaseName(encode, len, e2);
00643 if(ptr == nil)
00644 return nil;
00645 else
00646 return &ptr[len];
00647 }
00648
00649 char* TypeInfo::GetReturnType(char* encode, Environment* env)
00650 {
00651 for(;;)
00652 switch(*encode){
00653 case '_' :
00654 return encode + 1;
00655 case '\0' :
00656 return nil;
00657 default :
00658 encode = SkipType(encode, env);
00659 break;
00660 }
00661 }
00662
00663 char* TypeInfo::SkipType(char* ptr, Environment* env)
00664 {
00665 while(ptr != nil)
00666 switch(*ptr){
00667 case '\0' :
00668 case '_' :
00669 return nil;
00670 case 'S' :
00671 case 'U' :
00672 case 'C' :
00673 case 'V' :
00674 case 'P' :
00675 case 'R' :
00676 case 'A' :
00677 ++ptr;
00678 break;
00679 case 'F' :
00680 ptr = GetReturnType(ptr + 1, env);
00681 break;
00682 case 'T' :
00683 case 'Q' :
00684 return SkipName(ptr, env);
00685 case 'M' :
00686 ptr = SkipName(ptr + 1, env);
00687 break;
00688 default :
00689 if(*(unsigned char*)ptr < 0x80)
00690 return ptr + 1;
00691 else
00692 return SkipName(ptr, env);
00693 }
00694
00695 return ptr;
00696 }