Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

encoding.cc

Go to the documentation of this file.
00001 /*
00002   Copyright (C) 1997-2001 Shigeru Chiba, Tokyo Institute of Technology.
00003 
00004   Permission to use, copy, distribute and modify this software and   
00005   its documentation for any purpose is hereby granted without fee,        
00006   provided that the above copyright notice appear in all copies and that 
00007   both that copyright notice and this permission notice appear in 
00008   supporting documentation.
00009 
00010   Shigeru Chiba makes no representations about the suitability of this 
00011   software for any purpose.  It is provided "as is" without express or
00012   implied warranty.
00013 */
00014 
00015 /*
00016   This encoding is also interpreted by TypeInfo.  If you modify this
00017   file, check typeinfo.{h,cc} out as well.
00018 
00019   'b' boolean
00020   'c' char
00021   'i' int (signed, unsigned)
00022   's' short (short int)
00023   'l' long (long int)
00024   'j' long long
00025   'f' float
00026   'd' double
00027   'r' long double
00028   'v' void
00029 
00030   'T' template class (e.g. Foo<int,char> ==> T[3]Foo[2]ic.  [2] means
00031       the length of "ic".  It doesn't mean the number of template
00032       arguments.
00033   'e' ...
00034   '?' no return type.  the return type of constructors
00035   '*' non-type template parameter
00036 
00037   'S' singned
00038   'U' unsigned
00039   'C' const
00040   'V' volatile
00041 
00042   'P' pointer
00043   'R' reference
00044   'A' []
00045   'F' function (e.g. char foo(int) ==> Fi_c)
00046   'M' pointer to member (e.g. Type::* ==> M[4]Type)
00047 
00048   'Q' qualified class (e.g. X::YY ==> Q[2][1]X[2]YY, ::YY ==> Q[2][0][2]YY)
00049 
00050   [x] means (0x80 + x)
00051   '0' means :: (global scope)
00052 
00053   Special function names:
00054 
00055   operator + ==> +
00056   operator new[] ==> new[]
00057   operator <type> ==> @<encoded type>           cast operator
00058 */
00059 
00060 #include <string.h>
00061 #include <iostream.h>
00062 #include "encoding.h"
00063 #include "token.h"
00064 #include "ptree.h"
00065 #include "env.h"
00066 #include "mop.h"
00067 #include "typeinfo.h"
00068 
00069 Ptree* Encoding::bool_t = new LeafBOOLEAN("bool", 4);
00070 Ptree* Encoding::char_t = new LeafCHAR("char", 4);
00071 Ptree* Encoding::int_t = new LeafINT("int", 3);
00072 Ptree* Encoding::short_t = new LeafSHORT("short", 5);
00073 Ptree* Encoding::long_t = new LeafLONG("long", 4);
00074 Ptree* Encoding::float_t = new LeafFLOAT("float", 5);
00075 Ptree* Encoding::double_t = new LeafDOUBLE("double", 6);
00076 Ptree* Encoding::void_t = new LeafVOID("void", 4);
00077 
00078 Ptree* Encoding::signed_t = new LeafSIGNED("signed", 6);
00079 Ptree* Encoding::unsigned_t = new LeafUNSIGNED("unsigned", 8);
00080 Ptree* Encoding::const_t = new LeafCONST("const", 5);
00081 Ptree* Encoding::volatile_t = new LeafVOLATILE("volatile", 8);
00082 
00083 Ptree* Encoding::operator_name = new LeafReserved("operator", 8);
00084 Ptree* Encoding::new_operator = new LeafReserved("new", 3);
00085 Ptree* Encoding::anew_operator = new LeafReserved("new[]", 5);
00086 Ptree* Encoding::delete_operator = new LeafReserved("delete", 6);
00087 Ptree* Encoding::adelete_operator = new LeafReserved("delete[]", 8);
00088 
00089 Ptree* Encoding::star = new Leaf("*", 1);
00090 Ptree* Encoding::ampersand = new Leaf("&", 1);
00091 Ptree* Encoding::comma = new Leaf(",", 1);
00092 Ptree* Encoding::dots = new Leaf("...", 3);
00093 Ptree* Encoding::scope = new Leaf("::", 2);
00094 Ptree* Encoding::tilder = new Leaf("~", 1);
00095 Ptree* Encoding::left_paren = new Leaf("(", 1);
00096 Ptree* Encoding::right_paren = new Leaf(")", 1);
00097 Ptree* Encoding::left_bracket = new Leaf("[", 1);
00098 Ptree* Encoding::right_bracket = new Leaf("]", 1);
00099 Ptree* Encoding::left_angle = new Leaf("<", 1);
00100 Ptree* Encoding::right_angle = new Leaf(">", 1);
00101 
00102 const int DigitOffset = 0x80;
00103 
00104 void Encoding::Reset(Encoding& e)
00105 {
00106     len = e.len;
00107     if(len > 0)
00108         memmove(name, e.name, len);
00109 }
00110 
00111 char* Encoding::Get()
00112 {
00113     if(len == 0)
00114         return nil;
00115     else{
00116         char* s = new (GC) char[len + 1];
00117         memmove(s, name, len);
00118         s[len] = '\0';
00119         return s;
00120     }
00121 }
00122 
00123 void Encoding::Print(ostream& s, char* p)
00124 {
00125     unsigned char* ptr = (unsigned char*)p;
00126     for(;*ptr != '\0'; ++ptr)
00127         if(*ptr < 0x80)
00128             s << char(*ptr);
00129         else
00130             s << char(*ptr - 0x80 + '0');
00131 }
00132 
00133 // GetBaseName() returns "Foo" if ENCODE is "Q[2][1]X[3]Foo", for example.
00134 // If an error occurs, the function returns nil.
00135 
00136 char* Encoding::GetBaseName(char* encode, int& len, Environment*& env)
00137 {
00138     if(encode == nil){
00139         len = 0;
00140         return nil;
00141     }
00142 
00143     Environment* e = env;
00144     unsigned char* p = (unsigned char*)encode;
00145     if(*p == 'Q'){
00146         int n = p[1] - 0x80;
00147         p += 2;
00148         while(n-- > 1){
00149             int m = *p++;
00150             if(m == 'T')
00151                 m = GetBaseNameIfTemplate(p, e);
00152             else if(m < 0x80){          // error?
00153                 len = 0;
00154                 return nil;
00155             }
00156             else{                       // class name
00157                 m -= 0x80;
00158                 if(m <= 0){             // if global scope (e.g. ::Foo)
00159                     if(e != nil)
00160                         e = e->GetBottom();
00161                 }
00162                 else
00163                     e = ResolveTypedefName(e, (char*)p, m);
00164             }
00165 
00166             p += m;
00167         }
00168 
00169         env = e;
00170     }
00171 
00172     if(*p == 'T'){              // template class
00173         int m = p[1] - 0x80;
00174         int n = p[m + 2] - 0x80;
00175         len = m + n + 3;
00176         return (char*)p;
00177     }
00178     else if(*p < 0x80){         // error?
00179         len = 0;
00180         return nil;
00181     }
00182     else{
00183         len = *p - 0x80;
00184         return (char*)p + 1;
00185     }
00186 }
00187 
00188 Environment* Encoding::ResolveTypedefName(Environment* env,
00189                                           char* name, int len)
00190 {
00191     TypeInfo tinfo;
00192     Bind* bind;
00193     Class* c = nil;
00194 
00195     if(env != nil)
00196         if (env->LookupType(name, len, bind) && bind != nil)
00197             switch(bind->What()){
00198             case Bind::isClassName :
00199                 c = bind->ClassMetaobject();
00200                 break;
00201             case Bind::isTypedefName :
00202                 bind->GetType(tinfo, env);
00203                 c = tinfo.ClassMetaobject();
00204                 /* if (c == nil) */
00205                     env = nil;
00206                 break;
00207             default :
00208                 break;
00209             }
00210         else {
00211             env = env->LookupNamespace(name, len);
00212             /* env is nil if name is an unknown typedef name or namespace.
00213              */
00214         }
00215 
00216     if(c != nil)
00217         return c->GetEnvironment();
00218     else
00219         return env;
00220 }
00221 
00222 int Encoding::GetBaseNameIfTemplate(unsigned char* name, Environment*& e)
00223 {
00224     int m = name[0] - 0x80;
00225     if(m <= 0)
00226         return name[1] - 0x80 + 2;
00227 
00228     Bind* b;
00229     if(e != nil && e->LookupType((char*)&name[1], m, b))
00230         if(b != nil && b->What() == Bind::isTemplateClass){
00231             Class* c = b->ClassMetaobject();
00232             if(c != nil){
00233                 e = c->GetEnvironment();
00234                 return m + (name[m + 1] - 0x80) + 2;
00235             }
00236         }
00237 
00238     // the template name was not found.
00239     e = nil;
00240     return m + (name[m + 1] - 0x80) + 2;
00241 }
00242 
00243 unsigned char* Encoding::GetTemplateArguments(unsigned char* name, int& len)
00244 {
00245     int m = name[0] - 0x80;
00246     if(m <= 0){
00247         len = name[1] - 0x80;
00248         return &name[2];
00249     }
00250     else{
00251         len = name[m + 1] - 0x80;
00252         return &name[m + 2];
00253     }
00254 }
00255 
00256 void Encoding::CvQualify(Ptree* cv1, Ptree* cv2)
00257 {
00258     bool c = FALSE, v = FALSE;
00259     if(cv1 != nil && !cv1->IsLeaf())
00260         while(cv1 != nil){
00261             int kind = cv1->Car()->What();
00262             cv1 = cv1->Cdr();
00263             if(kind == CONST)
00264                 c = TRUE;
00265             else if(kind == VOLATILE)
00266                 v = TRUE;
00267         }
00268 
00269     if(cv2 != nil && !cv2->IsLeaf())
00270         while(cv2 != nil){
00271             int kind = cv2->Car()->What();
00272             cv2 = cv2->Cdr();
00273             if(kind == CONST)
00274                 c = TRUE;
00275             else if(kind == VOLATILE)
00276                 v = TRUE;
00277         }
00278 
00279     if(v)
00280         Insert('V');
00281 
00282     if(c)
00283         Insert('C');
00284 }
00285 
00286 void Encoding::GlobalScope()
00287 {
00288     Append(DigitOffset);
00289 }
00290 
00291 // SimpleName() is also used for operator names
00292 
00293 void Encoding::SimpleName(Ptree* id)
00294 {
00295     AppendWithLen(id->GetPosition(), id->GetLength());
00296 }
00297 
00298 // NoName() generates a internal name for no-name enum and class
00299 // declarations.
00300 
00301 void Encoding::NoName()
00302 {
00303     static int i = 0;
00304     static unsigned char name[] = "`0000";
00305     int n = i++;
00306     name[1] = n / 1000 + '0';
00307     name[2] = (n / 100) % 10 + '0';
00308     name[3] = (n / 10) % 10 + '0';
00309     name[4] = n % 10 + '0';
00310     AppendWithLen((char*)name, 5);
00311 }
00312 
00313 void Encoding::Template(Ptree* name, Encoding& args)
00314 {
00315     Append('T');
00316     SimpleName(name);
00317     AppendWithLen(args);
00318 }
00319 
00320 void Encoding::Qualified(int n)
00321 {
00322     if(len + 1 >= MaxNameLen)
00323         MopErrorMessage("Encoding::Qualified()",
00324                         "too long encoded name");
00325 
00326     memmove(name + 2, name, len);
00327     len += 2;
00328     name[0] = 'Q';
00329     name[1] = (unsigned char)(DigitOffset + n);
00330 }
00331 
00332 void Encoding::Destructor(Ptree* class_name)
00333 {
00334     int len = class_name->GetLength();
00335     Append((unsigned char)(DigitOffset + len + 1));
00336     Append('~');
00337     Append(class_name->GetPosition(), len);
00338 }
00339 
00340 void Encoding::PtrOperator(int t)
00341 {
00342     if(t == '*')
00343         Insert('P');
00344     else
00345         Insert('R');
00346 }
00347 
00348 void Encoding::PtrToMember(Encoding& encode, int n)
00349 {
00350     if(n < 2)
00351         Insert((char*)encode.name, encode.len);
00352     else{
00353         Insert((char*)encode.name, encode.len);
00354         Insert((unsigned char)(DigitOffset + n));
00355         Insert('Q');
00356     }
00357 
00358     Insert('M');
00359 }
00360 
00361 void Encoding::CastOperator(Encoding& type)
00362 {
00363     Append((unsigned char)(DigitOffset + type.len + 1));
00364     Append('@');
00365     Append((char*)type.name, type.len);
00366 }
00367 
00368 void Encoding::Insert(unsigned char c)
00369 {
00370     if(len >= MaxNameLen)
00371         MopErrorMessage("Encoding::Insert()",
00372                         "too long encoded name");
00373 
00374     if(len > 0)
00375         memmove(name + 1, name, len);
00376 
00377     ++len;
00378     name[0] = c;
00379 }
00380 
00381 void Encoding::Insert(char* str, int n)
00382 {
00383     if(len + n >= MaxNameLen)
00384         MopErrorMessage("Encoding::Insert()",
00385                         "too long encoded name");
00386 
00387     if(len > 0)
00388         memmove(&name[n], name, len);
00389 
00390     memmove(name, str, n);
00391     len += n;
00392 }
00393 
00394 void Encoding::Append(unsigned char c)
00395 {
00396     if(len >= MaxNameLen)
00397         MopErrorMessage("Encoding::Append()",
00398                         "too long encoded name");
00399 
00400     name[len++] = c;
00401 }
00402 
00403 void Encoding::Append(char* str, int n)
00404 {
00405     if(len + n >= MaxNameLen)
00406         MopErrorMessage("Encoding::Append(char*,int)",
00407                         "too long encoded name");
00408 
00409     memmove(&name[len], str, n);
00410     len += n;
00411 }
00412 
00413 void Encoding::AppendWithLen(char* str, int n)
00414 {
00415     if(len + n + 1 >= MaxNameLen)
00416         MopErrorMessage("Encoding::AppendWithLen()",
00417                         "too long encoded name");
00418 
00419     name[len++] = (unsigned char)(DigitOffset + n);
00420     memmove(&name[len], str, n);
00421     len += n;
00422 }
00423 
00424 Ptree* Encoding::MakePtree(unsigned char*& encoded, Ptree* decl)
00425 {
00426     Ptree* cv;
00427     Ptree* typespec = nil;
00428     if(decl != nil)
00429         decl = Ptree::List(decl);
00430 
00431     for(;;){
00432         cv = nil;
00433         switch(*encoded++){
00434         case 'b' :
00435             typespec = Ptree::Snoc(typespec, bool_t);
00436             goto finish;
00437         case 'c' :
00438             typespec = Ptree::Snoc(typespec, char_t);
00439             goto finish;
00440         case 'i' :
00441             typespec = Ptree::Snoc(typespec, int_t);
00442             goto finish;
00443         case 's' :
00444             typespec = Ptree::Snoc(typespec, short_t);
00445             goto finish;
00446         case 'l' :
00447             typespec = Ptree::Snoc(typespec, long_t);
00448             goto finish;
00449             break;
00450         case 'j' :
00451             typespec = Ptree::Nconc(typespec, Ptree::List(long_t, long_t));
00452             goto finish;
00453             break;
00454         case 'f' :
00455             typespec = Ptree::Snoc(typespec, float_t);
00456             goto finish;
00457             break;
00458         case 'd' :
00459             typespec = Ptree::Snoc(typespec, double_t);
00460             goto finish;
00461             break;
00462         case 'r' :
00463             typespec = Ptree::Nconc(typespec, Ptree::List(long_t, double_t));
00464             goto finish;
00465         case 'v' :
00466             typespec = Ptree::Snoc(typespec, void_t);
00467             goto finish;
00468         case 'e' :
00469             return dots;
00470         case '?' :
00471             goto finish;
00472         case 'Q' :
00473             typespec = Ptree::Snoc(typespec, MakeQname(encoded));
00474             goto finish;
00475         case 'S' :
00476             typespec = Ptree::Snoc(typespec, signed_t);
00477             break;
00478         case 'U' :
00479             typespec = Ptree::Snoc(typespec, unsigned_t);
00480             break;
00481         case 'C' :
00482             if(*encoded == 'V'){
00483                 ++encoded;
00484                 cv = Ptree::List(const_t, volatile_t);
00485             }
00486             else
00487                 cv = Ptree::List(const_t);
00488 
00489             goto const_or_volatile;
00490         case 'V' :
00491             cv = Ptree::List(volatile_t);
00492         const_or_volatile :
00493             switch(*encoded) {
00494             case 'M' :
00495             case 'P' :
00496             case 'R' :
00497                 decl = Ptree::Nconc(cv, decl);
00498                 break;
00499             case 'F' :
00500                 ++encoded;
00501                 goto cv_function;
00502             default :
00503                 typespec = Ptree::Nconc(cv, typespec);
00504                 break;
00505             }
00506             break;
00507         case 'M' :
00508             {
00509                 Ptree* ptr;
00510                 if(*encoded == 'Q')
00511                     ptr = MakeQname(++encoded);
00512                 else
00513                     ptr = MakeLeaf(encoded);
00514 
00515                 ptr = Ptree::List(ptr, scope, star);
00516                 decl = Ptree::Cons(ptr, decl);
00517             }
00518 
00519             goto pointer_or_reference;
00520         case 'P' :
00521             decl = Ptree::Cons(star, decl);
00522             goto pointer_or_reference;
00523         case 'R' :
00524             decl = Ptree::Cons(ampersand, decl);
00525         pointer_or_reference :
00526             if(*encoded == 'A' || *encoded == 'F')
00527                 decl = Ptree::List(Ptree::List(left_paren, decl,
00528                                                right_paren));
00529 
00530             break;
00531         case 'A' :
00532             decl = Ptree::Nconc(decl, Ptree::List(left_bracket,
00533                                                   right_bracket));
00534             break;
00535         case 'F' :
00536         cv_function :
00537             {
00538                 Ptree* args = nil;
00539                 while(*encoded != '\0'){
00540                     if(*encoded == '_'){
00541                         ++encoded;
00542                         break;
00543                     }
00544                     else if(*encoded == 'v'){
00545                         encoded += 2;
00546                         break;
00547                     }
00548 
00549                     if(args != nil)
00550                         args = Ptree::Snoc(args, comma);
00551 
00552                     args = Ptree::Snoc(args, MakePtree(encoded, nil));
00553                 }
00554 
00555                 decl = Ptree::Nconc(decl, Ptree::List(left_paren, args,
00556                                                       right_paren));
00557                 if(cv != nil)
00558                     decl = Ptree::Nconc(decl, cv);
00559             }
00560             break;
00561         case '\0' :
00562             goto finish;
00563         case 'T' :
00564             {
00565                 Ptree* tlabel = MakeLeaf(encoded);      
00566                 Ptree* args = nil;
00567                 int n = *encoded++ - DigitOffset;
00568                 unsigned char* stop = encoded + n;
00569                 while(encoded < stop){
00570                     if(args != nil)
00571                         args = Ptree::Snoc(args, comma);
00572 
00573                     args = Ptree::Snoc(args, MakePtree(encoded, nil));
00574                 }
00575 
00576                 tlabel = Ptree::List(tlabel,
00577                                 Ptree::List(left_angle, args, right_angle));
00578                 typespec = Ptree::Nconc(typespec, tlabel);
00579                 goto finish;
00580             }
00581         case '*' :
00582             goto error;
00583         default :
00584             if(*--encoded >= DigitOffset){
00585                 if(typespec == nil)
00586                     typespec = MakeLeaf(encoded);
00587                 else
00588                     typespec = Ptree::Snoc(typespec, MakeLeaf(encoded));
00589 
00590                 goto finish;
00591             }
00592         error :
00593             MopErrorMessage("TypeInfo::MakePtree()",
00594                             "sorry, cannot handle this type");
00595             break;
00596         }
00597     }
00598 
00599 finish :
00600     return Ptree::List(typespec, decl);
00601 }
00602 
00603 Ptree* Encoding::MakeQname(unsigned char*& encoded)
00604 {
00605     int n = *encoded++ - DigitOffset;
00606     Ptree* qname = nil;
00607     while(n-- > 0){
00608         Ptree* leaf = MakeLeaf(encoded);
00609         if(leaf != nil)
00610             qname = Ptree::Snoc(qname, leaf);
00611 
00612         if(n > 0)
00613             qname = Ptree::Snoc(qname, scope);
00614     }
00615 
00616     return qname;
00617 }
00618 
00619 Ptree* Encoding::MakeLeaf(unsigned char*& encoded)
00620 {
00621     Ptree* leaf;
00622     int len = *encoded++ - DigitOffset;
00623     if(len > 0)
00624         leaf = new Leaf((char*)encoded, len);
00625     else
00626         leaf = nil;
00627 
00628     encoded += len;
00629     return leaf;
00630 }
00631 
00632 bool Encoding::IsSimpleName(unsigned char* p)
00633 {
00634     return *p >= DigitOffset;
00635 }
00636 
00637 Ptree* Encoding::NameToPtree(char* name, int len)
00638 {
00639     if(name == nil)
00640         return nil;
00641 
00642     if(name[0] == 'n'){
00643         if(len == 5 && strncmp(name, "new[]", 5) == 0)
00644             return Ptree::List(operator_name, anew_operator);
00645         else if(len == 3 && strncmp(name, "new", 3) == 0)
00646             return Ptree::List(operator_name, new_operator);
00647     }
00648     else if(name[0] == 'd'){
00649         if(len == 8 && strncmp(name, "delete[]", 8) == 0)
00650             return Ptree::List(operator_name, adelete_operator);
00651         else if(len == 6 && strncmp(name, "delete", 6) == 0)
00652             return Ptree::List(operator_name, delete_operator);
00653     }
00654     else if(name[0] == '~')
00655         return Ptree::List(tilder, new Leaf(&name[1], len - 1));
00656     else if(name[0] == '@'){            // cast operator
00657         unsigned char* encoded = (unsigned char*)&name[1];
00658         return Ptree::List(operator_name, MakePtree(encoded, nil));
00659     }
00660 
00661     if(is_letter(name[0]))
00662         return new Leaf(name, len);
00663     else
00664         return Ptree::List(operator_name, new Leaf(name, len));
00665 }
00666 

Generated on Mon Feb 10 17:32:46 2003 for VFiasco Semantics Compiler by doxygen1.2.15