mummy
1.0.2
|
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("&"); break; 00882 case '\'' : encoded.append("'"); break; 00883 case '>' : encoded.append(">"); break; 00884 case '<' : encoded.append("<"); break; 00885 case '"' : encoded.append("""); 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 }