mummy  1.0.2
MummyUtilities.cxx
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 //
00003 //  $Id: MummyUtilities.cxx 470 2009-06-12 17:43:02Z hoffman $
00004 //
00005 //  $Author: hoffman $
00006 //  $Date: 2009-06-12 13:43:02 -0400 (Fri, 12 Jun 2009) $
00007 //  $Revision: 470 $
00008 //
00009 //  Copyright (C) 2006-2007 Kitware, Inc.
00010 //
00011 //----------------------------------------------------------------------------
00012 
00013 #include "MummyUtilities.h"
00014 #include "MummyLog.h"
00015 
00016 #include "cableClass.h"
00017 #include "cableClassType.h"
00018 #include "cableConstructor.h"
00019 #include "cableFunctionType.h"
00020 #include "cableNamed.h"
00021 #include "cablePointerType.h"
00022 #include "cableReferenceType.h"
00023 #include "cableType.h"
00024 #include "cableTypedef.h"
00025 
00026 #include "cxxFundamentalType.h"
00027 
00028 #include "gxsys/RegularExpression.hxx"
00029 #include "gxsys/SystemTools.hxx"
00030 #include "gxsys/ios/fstream"
00031 #include "gxsys/ios/sstream"
00032 #include "gxsys/stl/map"
00033 
00034 #ifdef _WIN32
00035 #include <windows.h> // only for "OutputDebugString"
00036 #endif // _WIN32
00037 
00038 #include "string.h" // strlen
00039 
00040 
00041 //----------------------------------------------------------------------------
00042 void Trace(const char *s)
00043 {
00044 #ifdef _WIN32
00045         OutputDebugString(s);
00046 #endif // _WIN32
00047 
00048         //LogInfo(mi_Info, << s);
00049 }
00050 
00051 
00052 //----------------------------------------------------------------------------
00053 void Emit(gxsys_ios::ostream &os, const char *s)
00054 {
00055         //Trace(s);
00056         os << s;
00057 }
00058 
00059 
00060 //----------------------------------------------------------------------------
00061 void EmitInt(gxsys_ios::ostream &os, const int i)
00062 {
00063         os << i;
00064 }
00065 
00066 
00067 //----------------------------------------------------------------------------
00068 void EmitUint(gxsys_ios::ostream &os, const unsigned int i)
00069 {
00070         os << i;
00071 }
00072 
00073 
00074 //----------------------------------------------------------------------------
00075 void EmitIndent(gxsys_ios::ostream &os, const unsigned int n)
00076 {
00077   // See also: indentString in EmitDocumentationBlock. If we change it here,
00078   // we probably will want to change it there also...
00079   //
00080         unsigned int i = 0;
00081         for (i= 0; i<n; ++i)
00082         {
00083                 Emit(os, "   ");
00084         }
00085 }
00086 
00087 
00088 //----------------------------------------------------------------------------
00089 void EmitFile(gxsys_ios::ostream &os, const char *filename)
00090 {
00091         gxsys_ios::ifstream file(filename);
00092         if (file)
00093         {
00094                 char line[4100];
00095                 while (!file.eof())
00096                 {
00097                         line[0] = 0;
00098                         file.getline(line, 4099);
00099                         os << line << gxsys_ios::endl;
00100                 }
00101         }
00102 }
00103 
00104 
00105 //----------------------------------------------------------------------------
00106 void WriteToFile(const char *filename, const char *s)
00107 {
00108         gxsys_ios::ofstream file;
00109         file.open(filename, gxsys_ios::ios_base::out | gxsys_ios::ios_base::trunc);
00110         if (file)
00111         {
00112                 file << s;
00113                 file.flush();
00114                 file.close();
00115         }
00116 }
00117 
00118 
00119 //----------------------------------------------------------------------------
00120 bool IsChar(const cable::Type *t)
00121 {
00122         return IsFundamental(t, cxx::FundamentalType::Char);
00123 }
00124 
00125 
00126 //----------------------------------------------------------------------------
00127 bool IsFundamental(const cable::Type *t, cxx::FundamentalType::Id tid)
00128 {
00129         if (cable::Type::FundamentalTypeId == t->GetTypeId())
00130         {
00131                 const cxx::FundamentalType *cxxft = cxx::FundamentalType::SafeDownCast(
00132                         t->GetCxxType().GetType());
00133 
00134                 if (cxxft)
00135                 {
00136                         return tid == cxxft->GetId();
00137                 }
00138         }
00139 
00140         return false;
00141 }
00142 
00143 
00144 //----------------------------------------------------------------------------
00145 bool IsObject(const cable::Type *t)
00146 {
00147         return cable::Type::ClassTypeId == t->GetTypeId();
00148 }
00149 
00150 
00151 //----------------------------------------------------------------------------
00152 bool IsVoid(const cable::Type *t)
00153 {
00154         return IsFundamental(t, cxx::FundamentalType::Void);
00155 }
00156 
00157 
00158 //----------------------------------------------------------------------------
00159 bool HasMapToType(const cable::Type *t)
00160 {
00161         if (IsObject(t))
00162         {
00163                 return HasAttribute(cable::ClassType::SafeDownCast(t)->GetClass(),
00164                         "gccxml(iwhMapToType");
00165         }
00166 
00167         if ((cable::Type::ReferenceTypeId == t->GetTypeId()) &&
00168                 IsObject(cable::ReferenceType::SafeDownCast(t)->GetTarget()))
00169         {
00170                 return HasAttribute(cable::ClassType::SafeDownCast(
00171                         cable::ReferenceType::SafeDownCast(t)->GetTarget())->GetClass(),
00172                         "gccxml(iwhMapToType");
00173         }
00174 
00175         return false;
00176 }
00177 
00178 
00179 //----------------------------------------------------------------------------
00180 gxsys_stl::string GetMapToType(const cable::Type *t)
00181 {
00182         gxsys_stl::string s;
00183 
00184         if (IsObject(t))
00185         {
00186                 s = ExtractMapToType(cable::ClassType::SafeDownCast(t)->GetClass());
00187         }
00188         else if ((cable::Type::ReferenceTypeId == t->GetTypeId()) &&
00189                 IsObject(cable::ReferenceType::SafeDownCast(t)->GetTarget()))
00190         {
00191                 s = ExtractMapToType(cable::ClassType::SafeDownCast(
00192                         cable::ReferenceType::SafeDownCast(t)->GetTarget())->GetClass());
00193         }
00194 
00195         return s;
00196 }
00197 
00198 
00199 //----------------------------------------------------------------------------
00200 gxsys_stl::string GetStringMethod(const cable::Type *t)
00201 {
00202         gxsys_stl::string s;
00203 
00204         if (IsObject(t))
00205         {
00206                 s = ExtractStringMethod(cable::ClassType::SafeDownCast(t)->GetClass());
00207         }
00208         else if ((cable::Type::ReferenceTypeId == t->GetTypeId()) &&
00209                 IsObject(cable::ReferenceType::SafeDownCast(t)->GetTarget()))
00210         {
00211                 s = ExtractStringMethod(cable::ClassType::SafeDownCast(
00212                         cable::ReferenceType::SafeDownCast(t)->GetTarget())->GetClass());
00213         }
00214 
00215         return s;
00216 }
00217 
00218 
00219 //----------------------------------------------------------------------------
00220 bool IsCharPointer(const cable::Type *t)
00221 {
00222         return IsFundamentalPointer(t, cxx::FundamentalType::Char);
00223 }
00224 
00225 
00226 //----------------------------------------------------------------------------
00227 bool IsCharPointerPointer(const cable::Type *t)
00228 {
00229         return IsFundamentalPointerPointer(t, cxx::FundamentalType::Char);
00230 }
00231 
00232 
00233 //----------------------------------------------------------------------------
00234 bool IsFundamentalPointer(const cable::Type *t, cxx::FundamentalType::Id tid)
00235 {
00236         if (cable::Type::PointerTypeId == t->GetTypeId())
00237         {
00238                 return IsFundamental(cable::PointerType::SafeDownCast(t)->GetTarget(), tid);
00239         }
00240 
00241         return false;
00242 }
00243 
00244 
00245 //----------------------------------------------------------------------------
00246 bool IsFundamentalPointerPointer(const cable::Type *t, cxx::FundamentalType::Id tid)
00247 {
00248         if (cable::Type::PointerTypeId == t->GetTypeId())
00249         {
00250                 return IsFundamentalPointer(cable::PointerType::SafeDownCast(t)->GetTarget(), tid);
00251         }
00252 
00253         return false;
00254 }
00255 
00256 
00257 //----------------------------------------------------------------------------
00258 bool IsObjectPointer(const cable::Type *t)
00259 {
00260         if (cable::Type::PointerTypeId == t->GetTypeId())
00261         {
00262                 return IsObject(cable::PointerType::SafeDownCast(t)->GetTarget());
00263         }
00264 
00265         return false;
00266 }
00267 
00268 
00269 //----------------------------------------------------------------------------
00270 bool IsObjectPointerReference(const cable::Type *t)
00271 {
00272         if (cable::Type::ReferenceTypeId == t->GetTypeId())
00273         {
00274                 return IsObjectPointer(cable::ReferenceType::SafeDownCast(t)->GetTarget());
00275         }
00276 
00277         return false;
00278 }
00279 
00280 
00281 //----------------------------------------------------------------------------
00282 bool IsVoidPointer(const cable::Type *t)
00283 {
00284         return IsFundamentalPointer(t, cxx::FundamentalType::Void);
00285 }
00286 
00287 
00288 //----------------------------------------------------------------------------
00289 const char *GetAccessString(cable::Context::Access access)
00290 {
00291         if (cable::Context::Public == access)
00292                 return "public";
00293 
00294         if (cable::Context::Protected == access)
00295                 return "protected";
00296 
00297         if (cable::Context::Private == access)
00298                 return "private";
00299 
00300         LogError(me_InvalidArg, << "ERROR_invalid_input_to_GetAccessString");
00301         return "ERROR_invalid_input_to_GetAccessString";
00302 }
00303 
00304 
00305 //----------------------------------------------------------------------------
00306 const cable::Class *GetParentClass(const cable::Class *c)
00307 {
00308         const cable::Class *parent = 0;
00309 
00310         if (c)
00311         {
00312                 gxsys_stl::vector<cable::Class *> bases;
00313                 size_t basecount = 0;
00314                 gxsys_stl::vector<cable::Class *>::iterator it;
00315 
00316                 c->GetBaseClasses(bases);
00317                 basecount = bases.size();
00318 
00319                 if (0 == basecount)
00320                 {
00321                 }
00322                 else if (1 == basecount)
00323                 {
00324                         parent = *bases.begin();
00325                 }
00326                 else
00327                 {
00328                         LogError(
00329                                 me_MoreThanOneBaseClass,
00330                                 << "GetParentClass returning 0 because there is more than one base for class '"
00331                                 << c->GetName() << "'"
00332                                 );
00333                 }
00334         }
00335 
00336         return parent;
00337 }
00338 
00339 
00340 //----------------------------------------------------------------------------
00341 bool ClassIsA(const cable::Class *c, const gxsys_stl::string& parent)
00342 {
00343         bool isa = false;
00344         const cable::Class *cIt = c;
00345 
00346         while (!isa && cIt != NULL)
00347         {
00348                 if (GetFullyQualifiedNameForCPlusPlus(cIt) == parent)
00349                 {
00350                         isa = true;
00351                 }
00352                 else
00353                 {
00354                         cIt = GetParentClass(cIt);
00355                 }
00356         }
00357 
00358         return isa;
00359 }
00360 
00361 
00362 //----------------------------------------------------------------------------
00363 bool ValidateBaseClasses(const cable::Class *c)
00364 {
00365         bool validated = false;
00366         gxsys_stl::vector<cable::Class *> bases;
00367         size_t basecount = 0;
00368         gxsys_stl::vector<cable::Class *>::iterator it;
00369 
00370         c->GetBaseClasses(bases);
00371         basecount = bases.size();
00372 
00373         if (0 == basecount)
00374         {
00375                 validated = true;
00376         }
00377         else if (1 == basecount)
00378         {
00379                 it = bases.begin();
00380                 validated = ValidateBaseClasses(*it);
00381         }
00382         else
00383         {
00384                 LogError(
00385                         me_MoreThanOneBaseClass,
00386                         << "ValidateBaseClasses returning false because there is more than one base for class '"
00387                         << c->GetName() << "'"
00388                         );
00389         }
00390 
00391         return validated;
00392 }
00393 
00394 
00395 //----------------------------------------------------------------------------
00396 gxsys_stl::string GetSimpleName(const cable::Named *n)
00397 {
00398         gxsys_stl::string s;
00399 
00400         if (n)
00401         {
00402                 s = n->GetName();
00403         }
00404         else
00405         {
00406                 s = "ERROR_invalid_input_to_GetSimpleName";
00407                 LogError(me_InvalidArg, << s.c_str());
00408         }
00409 
00410         return s;
00411 }
00412 
00413 
00414 //----------------------------------------------------------------------------
00415 gxsys_stl::string GetFullyQualifiedName(const cable::Named *n, const char *sep)
00416 {
00417         gxsys_stl::string s;
00418 
00419         if (n && sep && n->GetContext())
00420         {
00421                 s = GetFullyQualifiedName(n->GetContext(), sep);
00422 
00423                 // Do not emit a "leading separator" at global scope:
00424                 //
00425                 if (s == "::")
00426                 {
00427                         s = "";
00428                 }
00429                 else
00430                 {
00431                         s += sep;
00432                 }
00433 
00434                 s += n->GetName();
00435         }
00436         else if (n && sep)
00437         {
00438                 s = n->GetName();
00439         }
00440         else
00441         {
00442                 s = "ERROR_invalid_input_to_GetFullyQualifiedName";
00443                 LogError(me_InvalidArg, << s.c_str());
00444         }
00445 
00446         return s;
00447 }
00448 
00449 
00450 //----------------------------------------------------------------------------
00451 gxsys_stl::string GetFullyQualifiedLengthPrefixedName(const cable::Named *n, const char *sep)
00452 {
00453         gxsys_stl::string s;
00454 
00455         if (n && sep && n->GetContext())
00456         {
00457                 s = GetFullyQualifiedLengthPrefixedName(n->GetContext(), sep);
00458 
00459                 // Do not emit a "leading separator" at global scope:
00460                 //
00461                 if (s == "::")
00462                 {
00463                         s = "";
00464                 }
00465                 else
00466                 {
00467                         s += sep;
00468                 }
00469 
00470                 gxsys_ios::ostringstream oss;
00471                 oss << strlen(n->GetName());
00472                 s += oss.str();
00473 
00474                 s += n->GetName();
00475         }
00476         else if (n && sep)
00477         {
00478                 s = n->GetName();
00479         }
00480         else
00481         {
00482                 s = "ERROR_invalid_input_to_GetFullyQualifiedLengthPrefixedName";
00483                 LogError(me_InvalidArg, << s.c_str());
00484         }
00485 
00486         return s;
00487 }
00488 
00489 
00490 //----------------------------------------------------------------------------
00491 gxsys_stl::string GetFullyQualifiedNameForCPlusPlus(const cable::Named *n)
00492 {
00493         return GetFullyQualifiedName(n, "::");
00494 }
00495 
00496 
00497 //----------------------------------------------------------------------------
00498 gxsys_stl::string GetFullyQualifiedNameForCSharp(const cable::Named *n)
00499 {
00500         return GetFullyQualifiedName(n, ".");
00501 }
00502 
00503 
00504 //----------------------------------------------------------------------------
00505 gxsys_stl::string GetFullyQualifiedCPlusPlusTypeIdName(const cable::Named *n)
00506 {
00507         gxsys_stl::string s("ERROR_unknown_compiler_in_GetFullyQualifiedCPlusPlusTypeIdName");
00508 
00509 #if defined(_MSC_VER)
00510         s = "class ";
00511         s += GetFullyQualifiedNameForCPlusPlus(n);
00512 #elif defined(__GNUC__)
00513         s = GetFullyQualifiedLengthPrefixedName(n, "");
00514 #endif
00515 
00516         return s;
00517 }
00518 
00519 
00520 //----------------------------------------------------------------------------
00521 bool EquivalentTypedefNameExists(const cable::Class* c, const cable::FunctionType *target, gxsys_stl::string& s)
00522 {
00523         s = "";
00524 
00525         // Look through the typedefs of the target class and return the name of the
00526         // first one found that matches the function pointer type inside of 't'...
00527 
00528         for (cable::Context::Iterator it = c->Begin(); it != c->End() && s == ""; ++it)
00529         {
00530                 cable::Typedef *td = cable::Typedef::SafeDownCast(*it);
00531 
00532                 if (td && (cable::Context::Public == it.GetAccess()))
00533                 {
00534                         gxsys_stl::string tname(td->GetName());
00535 
00536                         cable::PointerType *pt = cable::PointerType::SafeDownCast(td->GetType());
00537                         cable::FunctionType *ft = 0;
00538                         if (pt)
00539                         {
00540                                 ft = cable::FunctionType::SafeDownCast(pt->GetTarget());
00541                         }
00542 
00543                         if (ft && ft == target)
00544                         {
00545                                 s = tname;
00546                         }
00547                 }
00548         }
00549 
00550         return (s != "");
00551 }
00552 
00553 
00554 //----------------------------------------------------------------------------
00555 bool HasAttribute(const cable::SourceObject *o, const char *attr)
00556 {
00557         gxsys_stl::string atts(o->GetAttributes());
00558         if (atts != "")
00559         {
00560                 if (gxsys_stl::string::npos != atts.find(attr))
00561                 {
00562                         return true;
00563                 }
00564         }
00565 
00566         return false;
00567 }
00568 
00569 
00570 //----------------------------------------------------------------------------
00571 bool IsUtilityClass(const cable::Class *c)
00572 {
00573         return HasAttribute(c, "gccxml(iwhUtility)");
00574 }
00575 
00576 
00577 //----------------------------------------------------------------------------
00578 gxsys_stl::string ExtractAttribute(const gxsys_stl::string& atts, const gxsys_stl::string& attBase)
00579 {
00580         gxsys_stl::string extracted;
00581         bool hasAtt = false;
00582 
00583         if (gxsys_stl::string::npos != atts.find(gxsys_stl::string("gccxml(") + attBase))
00584         {
00585                 hasAtt = true;
00586         }
00587 
00588         if (hasAtt)
00589         {
00590                 gxsys::RegularExpression re;
00591                 re.compile((gxsys_stl::string("(gccxml\\(")+attBase+")([^\\)]*)(\\))").c_str());
00592                 if (re.find(atts.c_str()))
00593                 {
00594                         extracted = re.match(2);
00595                 }
00596         }
00597 
00598         return extracted;
00599 }
00600 
00601 
00602 //----------------------------------------------------------------------------
00603 gxsys_stl::string ExtractAttribute(const cable::SourceObject *o, const gxsys_stl::string& attBase)
00604 {
00605         gxsys_stl::string atts(o->GetAttributes());
00606         return ExtractAttribute(atts, attBase);
00607 }
00608 
00609 
00610 //----------------------------------------------------------------------------
00611 gxsys_stl::string ExtractArraySize(const gxsys_stl::string& atts)
00612 {
00613         return ExtractAttribute(atts, "iwhArraySize");
00614 }
00615 
00616 
00617 //----------------------------------------------------------------------------
00618 gxsys_stl::string ExtractImplementsInterface(const gxsys_stl::string& atts)
00619 {
00620         return ExtractAttribute(atts, "iwhImplementsInterface");
00621 }
00622 
00623 
00624 //----------------------------------------------------------------------------
00625 gxsys_stl::string ExtractMapToType(const cable::SourceObject *o)
00626 {
00627         return ExtractAttribute(o, "iwhMapToType");
00628 }
00629 
00630 
00631 //----------------------------------------------------------------------------
00632 gxsys_stl::string ExtractStringMethod(const cable::SourceObject *o)
00633 {
00634         return ExtractAttribute(o, "iwhStringMethod");
00635 }
00636 
00637 
00638 //----------------------------------------------------------------------------
00639 gxsys_stl::string GetMappedTypeName(const cable::Class *c, bool fullyQualified)
00640 {
00641         gxsys_stl::string typeName(ExtractMapToType(c));
00642 
00643         if (typeName == "string")
00644         {
00645                 typeName = "string";
00646         }
00647         else
00648         {
00649                 if (fullyQualified)
00650                 {
00651                         typeName = GetFullyQualifiedNameForCSharp(c);
00652                 }
00653                 else
00654                 {
00655                         typeName = GetSimpleName(c);
00656                 }
00657         }
00658 
00659         return typeName;
00660 }
00661 
00662 
00663 //----------------------------------------------------------------------------
00664 gxsys_stl::string GetWrappedClassName(const cable::Class *c)
00665 {
00666         return GetMappedTypeName(c, false);
00667 }
00668 
00669 
00670 //----------------------------------------------------------------------------
00671 gxsys_stl::string GetWrappedClassNameFullyQualified(const cable::Class *c)
00672 {
00673         return GetMappedTypeName(c, true);
00674 }
00675 
00676 
00677 //----------------------------------------------------------------------------
00678 static gxsys_stl::map<int, int> suppressed_msg_values;
00679 
00680 
00681 //----------------------------------------------------------------------------
00682 void SuppressMsg(const int n)
00683 {
00684         suppressed_msg_values[n] = n;
00685 }
00686 
00687 
00688 //----------------------------------------------------------------------------
00689 bool ShouldLogMsg(const int n)
00690 {
00691         gxsys_stl::map<int, int>::iterator it = suppressed_msg_values.find(n);
00692         return it == suppressed_msg_values.end();
00693 }
00694 
00695 
00696 //----------------------------------------------------------------------------
00697 static gxsys_stl::vector<int> error_values;
00698 
00699 
00700 //----------------------------------------------------------------------------
00701 void LogMsg(const gxsys_stl::string&, const unsigned long, const gxsys_stl::string& label, const int n)
00702 {
00703         if (label == "error")
00704         {
00705                 if (n)
00706                 {
00707                         error_values.push_back(n);
00708                 }
00709                 else
00710                 {
00711                         gxsys_ios::cerr << "error: 'error' LogMsg n value should be non-zero...";
00712                         error_values.push_back(me_InternalError);
00713                 }
00714         }
00715 }
00716 
00717 
00718 //----------------------------------------------------------------------------
00719 int GetErrorCount()
00720 {
00721         return static_cast<int>(error_values.size());
00722 }
00723 
00724 
00725 //----------------------------------------------------------------------------
00726 int GetNthErrorValue(int n)
00727 {
00728         if (n >= 0 && n < GetErrorCount())
00729         {
00730                 return error_values[n];
00731         }
00732 
00733         return 0;
00734 }
00735 
00736 
00737 //----------------------------------------------------------------------------
00738 int GetFirstErrorValue()
00739 {
00740         return GetNthErrorValue(0);
00741 }
00742 
00743 
00744 //----------------------------------------------------------------------------
00745 int GetMostRecentErrorValue()
00746 {
00747         return GetNthErrorValue(GetErrorCount()-1);
00748 }
00749 
00750 
00751 //----------------------------------------------------------------------------
00752 const cable::Constructor* FindNonAbstractPublicDefaultConstructor(const cable::Class *c)
00753 {
00754         const cable::Constructor* ctor = 0;
00755 
00756         if (!c->GetAbstract())
00757         {
00758                 for (cable::Context::Iterator it = c->Begin(); 0 == ctor && it != c->End(); ++it)
00759                 {
00760                         cable::Constructor *ctorCandidate = cable::Constructor::SafeDownCast(*it);
00761 
00762                         if (ctorCandidate &&
00763                                 cable::Context::Public == it.GetAccess() &&
00764                                 0 == ctorCandidate->GetFunctionType()->GetNumberOfRequiredArguments())
00765                         {
00766                                 ctor = ctorCandidate;
00767                                 break;
00768                         }
00769                 }
00770         }
00771 
00772         return ctor;
00773 }
00774 
00775 
00776 //----------------------------------------------------------------------------
00777 gxsys_stl::string GetCPlusPlusZeroInitializerExpression(const cable::Type *t)
00778 {
00779         gxsys_stl::string s;
00780 
00781         switch (t->GetTypeId())
00782         {
00783         case cable::Type::ClassTypeId:
00784                 s = "memset";
00785                 break;
00786 
00787         case cable::Type::EnumerationTypeId:
00788                 s = "cast";
00789                 break;
00790 
00791         case cable::Type::FundamentalTypeId:
00792         case cable::Type::PointerTypeId:
00793                 s = "0";
00794                 break;
00795 
00796         default:
00797                 s = "error: unhandled cable::Type in GetCPlusPlusZeroInitializerExpression";
00798                 LogError(me_InternalError, << s.c_str());
00799                 break;
00800         }
00801 
00802         return s;
00803 }
00804 
00805 
00806 //----------------------------------------------------------------------------
00807 gxsys_stl::string GetCsharpZeroInitializerExpression(const cable::Type *t)
00808 {
00809         gxsys_stl::string s;
00810 
00811         switch (t->GetTypeId())
00812         {
00813         case cable::Type::ClassTypeId:
00814                 s = "null";
00815                 break;
00816 
00817         case cable::Type::EnumerationTypeId:
00818                 s = "cast";
00819                 break;
00820 
00821         case cable::Type::FundamentalTypeId:
00822         case cable::Type::PointerTypeId:
00823                 s = "0";
00824                 break;
00825 
00826         default:
00827                 s = "error: unhandled cable::Type in GetCsharpZeroInitializerExpression";
00828                 LogError(me_InternalError, << s.c_str());
00829                 break;
00830         }
00831 
00832         return s;
00833 }
00834 
00835 
00836 //----------------------------------------------------------------------------
00837 bool BlockContains(const gxsys_stl::vector<gxsys_stl::string>& block, const char *value)
00838 {
00839         gxsys_stl::vector<gxsys_stl::string>::const_iterator blockIt;
00840 
00841         for (blockIt = block.begin(); blockIt!=block.end(); ++blockIt)
00842         {
00843                 if (strstr(blockIt->c_str(), value))
00844                 {
00845                         return true;
00846                 }
00847         }
00848 
00849         return false;
00850 }
00851 
00852 
00853 //----------------------------------------------------------------------------
00854 bool ShouldEmitComment(const char *comment)
00855 {
00856         gxsys::RegularExpression re;
00857         re.compile("//[\\t ]*Description:[\\t ]*");
00858         if (re.find(comment))
00859         {
00860                 return false;
00861         }
00862 
00863         return true;
00864 }
00865 
00866 
00867 //----------------------------------------------------------------------------
00868 gxsys_stl::string EncodeStringForXml(const char *s)
00869 {
00870         gxsys_stl::string encoded;
00871 
00872         if (s)
00873         {
00874                 size_t i = 0;
00875                 size_t n = strlen(s);
00876 
00877                 for (i= 0; i<n; ++i)
00878                 {
00879                         switch (s[i])
00880                         {
00881                         case '&'  :  encoded.append("&amp;");   break;
00882                         case '\'' :  encoded.append("&apos;");  break;
00883                         case '>'  :  encoded.append("&gt;");    break;
00884                         case '<'  :  encoded.append("&lt;");    break;
00885                         case '"'  :  encoded.append("&quot;");  break;
00886 
00887                         default   :  encoded += s[i];           break;
00888                         }
00889                 }
00890         }
00891 
00892         return encoded;
00893 }
00894 
00895 
00896 // Valid XML doc tags are:
00897 //
00898 //"c"
00899 //"code"
00900 //"description"
00901 //"example"
00902 //"exception "
00903 //"include"
00904 //"item"
00905 //"list"
00906 //"listheader"
00907 //"para"
00908 //"param"
00909 //"paramref"
00910 //"permission"
00911 //"remarks"
00912 //"returns"
00913 //"see"
00914 //"seealso"
00915 //"summary"
00916 //"term"
00917 //"typeparam"
00918 //"typeparamref"
00919 //"value"
00920 
00921 
00922 //----------------------------------------------------------------------------
00923 void EmitDocumentationBlock(gxsys_ios::ostream &os, const gxsys_stl::vector<gxsys_stl::string>& block, const unsigned int indent, bool isClassDoc)
00924 {
00925   // See also: EmitIndent. If we change indentString here,
00926   // we probably will want to change it there also...
00927   //
00928         gxsys::String indentString = "";
00929         for (unsigned int i= 0; i<indent; ++i)
00930           {
00931                 indentString+="   ";
00932           }
00933 
00934         gxsys::String xmlTag = "summary";
00935 
00936         gxsys_stl::map<gxsys_stl::string, gxsys_stl::string> tagBody;
00937 
00938   gxsys_stl::vector<gxsys_stl::string>::const_iterator blockIt;
00939         gxsys_stl::string line;
00940 
00941         bool isXmlBlock =
00942     (BlockContains(block, "<summary>") && BlockContains(block, "</summary>")) ||
00943                 (BlockContains(block, "<remarks>") && BlockContains(block, "</remarks>"));
00944         
00945         gxsys::RegularExpression descRE;
00946         descRE.compile(gxsys_stl::string("Description:").c_str());
00947         gxsys::RegularExpression nameRE;
00948         nameRE.compile(gxsys_stl::string("\\.NAME").c_str()); 
00949         gxsys::RegularExpression seeRE;
00950         seeRE.compile(gxsys_stl::string("\\.SECTION[\\t ]+[Ss][Ee][Ee][\\t ]+[Aa][Ll][Ss][Oo]").c_str());
00951         gxsys::RegularExpression secRE;
00952         secRE.compile(gxsys_stl::string("\\.SECTION").c_str());
00953         gxsys::RegularExpression noSpaceRE;
00954         noSpaceRE.compile(gxsys_stl::string("[^ ]+").c_str());
00955 
00956   for (blockIt = block.begin(); blockIt!=block.end(); ++blockIt)
00957           {
00958                 line = *blockIt;
00959 
00960                 if (isClassDoc && !isXmlBlock)
00961                   {
00962                         //If it matches a .NAME section add to summary
00963                         if (nameRE.find(line))
00964                           {
00965                                 gxsys::SystemTools::ReplaceString(line,nameRE.match(0).c_str(),"");
00966                                 xmlTag = "summary";
00967                           }
00968                         //If it matches a .SECTION see also section add to see also
00969                         else if (seeRE.find(line))
00970                           {
00971                                 gxsys::SystemTools::ReplaceString(line,seeRE.match(0).c_str(),"");
00972                                 xmlTag = "seealso";
00973                           }
00974                         //If it matches a .SECTION * section add to remarks
00975                         else if (secRE.find(line))
00976                           {                     
00977                                 gxsys::SystemTools::ReplaceString(line,secRE.match(0).c_str(),"");
00978                                 xmlTag = "remarks";
00979                           }
00980                         //If it matches a Description: section add to summary
00981                         else if (descRE.find(line))
00982                           {
00983                                 gxsys::SystemTools::ReplaceString(line,descRE.match(0).c_str(),"");
00984                                 xmlTag = "summary";
00985                           }
00986                   }
00987 
00988     if (ShouldEmitComment(line.c_str()))
00989             {
00990                         if (isXmlBlock)
00991       {
00992         EmitIndent(os, indent);
00993 
00994         if (gxsys::SystemTools::StringStartsWith(line.c_str(), "///"))
00995           {
00996           Emit(os, line.c_str());
00997           }
00998         else if (gxsys::SystemTools::StringStartsWith(line.c_str(), "//"))
00999           {
01000           Emit(os, "/");
01001           Emit(os, line.c_str());
01002           }
01003         else
01004           {
01005           Emit(os, "///");
01006           Emit(os, line.c_str());
01007           }
01008         Emit(os,"\n");
01009         }
01010       else
01011         {
01012                                 line = EncodeStringForXml(line.c_str());
01013 
01014         //handle code in comments
01015                   gxsys::SystemTools::ReplaceString(line,"\\code","<code>");
01016                         gxsys::SystemTools::ReplaceString(line,"\\endcode","</code>");
01017 
01018         if (gxsys::SystemTools::StringStartsWith(line.c_str(), "///"))
01019           {
01020           tagBody[xmlTag]+=indentString+line+"\n";
01021           }
01022         else if (gxsys::SystemTools::StringStartsWith(line.c_str(), "//"))
01023           {
01024           tagBody[xmlTag]+=indentString+"/"+line+"\n";
01025           }
01026         else
01027           {
01028           tagBody[xmlTag]+=indentString+"///"+line+"\n";
01029           }
01030         }
01031                 }
01032           }
01033 
01034         if(tagBody["summary"] != "")
01035           {
01036                 gxsys::String beginTag = indentString+"/// <summary>\n";
01037                 gxsys::String endTag = indentString+"/// </summary>\n";
01038                 Emit(os,beginTag.c_str());
01039                 Emit(os,(tagBody["summary"]).c_str());
01040                 Emit(os,endTag.c_str());
01041           }
01042 
01043         if(tagBody["remarks"] != "")
01044           {
01045                 gxsys::String beginTag = indentString+"/// <remarks>\n";
01046                 gxsys::String endTag = indentString+"/// </remarks>\n";
01047                 Emit(os,beginTag.c_str());
01048                 Emit(os,(tagBody["remarks"]).c_str());
01049                 Emit(os,endTag.c_str());
01050           }
01051 
01052   if(tagBody["seealso"] != "")
01053           {
01054                 gxsys::String beginTag = indentString+"/// <seealso>\n";
01055                 gxsys::String endTag = indentString+"/// </seealso>\n";
01056                 Emit(os, beginTag.c_str());
01057                 Emit(os, tagBody["seealso"].c_str());
01058                 Emit(os, endTag.c_str());
01059           }
01060 }
01061 
01062 
01063 //----------------------------------------------------------------------------
01064 gxsys_stl::string ExtractDerivedName(const char *s, const cable::Named *n, bool verbose)
01065 {
01066         gxsys_stl::string name;
01067         gxsys_stl::string derivedName;
01068         gxsys_stl::string c1to2;
01069         gxsys_stl::string c1to3;
01070 
01071         if (s)
01072         {
01073                 name = s;
01074         }
01075 
01076         if (s && strlen(s)>2)
01077         {
01078                 c1to2 = name.substr(0, 2);
01079         }
01080 
01081         if (s && strlen(s)>3)
01082         {
01083                 c1to3 = name.substr(0, 3);
01084         }
01085 
01086         if ((c1to3 == "Get") || (c1to3 == "get"))
01087         {
01088                 derivedName = name.substr(3);
01089         }
01090         else if ((c1to3 == "Set") || (c1to3 == "set"))
01091         {
01092                 derivedName = name.substr(3);
01093         }
01094         else if (c1to2 == "m_")
01095         {
01096                 derivedName = name.substr(2);
01097         }
01098         else
01099         {
01100                 derivedName = name;
01101 
01102                 if (n && verbose)
01103                 {
01104                         LogFileLineInfoMsg(n->GetFile(), n->GetLine(), mi_VerboseInfo,
01105                                 "ExtractDerivedName could not extract derivedName from name: "
01106                                 << name << ". Using name as-is...");
01107                 }
01108         }
01109 
01110         return derivedName;
01111 }