1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Main program file for HelpGen 
   4 // Author:      Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   8 // Copyright:   (c) 1999 VZ 
  10 ///////////////////////////////////////////////////////////////////////////// 
  15    (i) small fixes in the current version 
  17    +1. Quote special TeX characters like '&' and '_' (=> derive from wxFile) 
  19     3. Document global variables 
  22    (ii) plans for version 2 
  23     1. Use wxTextFile for direct file access to avoid one scan method problems 
  27 // ============================================================================= 
  29 // ============================================================================= 
  31 // ----------------------------------------------------------------------------- 
  33 // ----------------------------------------------------------------------------- 
  36 #include "wx/wxprec.h" 
  39     #include <wx/string.h> 
  44 // C++ parsing classes 
  51 // ----------------------------------------------------------------------------- 
  53 // ----------------------------------------------------------------------------- 
  55 // return the label for the given function name 
  56 static wxString 
MakeLabel(const char *classname
, const char *funcname
); 
  58 // quotes special TeX characters in place 
  59 static void TeXFilter(wxString
* str
); 
  61 // ----------------------------------------------------------------------------- 
  63 // ----------------------------------------------------------------------------- 
  65 // add a function which sanitazes the string before writing it to the file 
  66 class wxTeXFile 
: public wxFile
 
  69     wxTeXFile() : wxFile() { } 
  71     bool WriteTeX(const wxString
& s
) 
  76         return wxFile::Write(t
); 
  80 class HelpGenVisitor 
: public spVisitor
 
  86     virtual void VisitFile( spFile
& fl 
); 
  87     virtual void VisitClass( spClass
& cl 
); 
  88     virtual void VisitEnumeration( spEnumeration
& en 
); 
  89     virtual void VisitTypeDef( spTypeDef
& td 
); 
  90     virtual void VisitAttribute( spAttribute
& attr 
); 
  91     virtual void VisitOperation( spOperation
& op 
); 
  92     virtual void VisitParameter( spParameter
& param 
); 
  96     // shut up g++ warning (ain't it stupid?) 
  97     virtual ~HelpGenVisitor() { } 
 100     // (re)initialize the state 
 103     // insert documentation for enums/typedefs coming immediately before the 
 104     // class declaration into the class documentation 
 105     void InsertTypedefDocs(); 
 106     void InsertEnumDocs(); 
 108     // write the headers for corresponding sections (only once) 
 109     void InsertDataStructuresHeader(); 
 110     void InsertMethodsHeader(); 
 112     // terminate the function documentation if it was started 
 113     void CloseFunction(); 
 115     wxTeXFile m_file
;  // file we're writing to now 
 118     bool m_inClass
,         // TRUE after file successfully opened 
 119          m_inTypesSection
,  // enums & typedefs go there 
 120          m_inMethodSection
, // functions go here 
 121          m_isFirstParam
,    // first parameter of current function? 
 122          m_inFunction
;      // we're parsing a function declaration 
 124     // holders for "saved" documentation 
 125     wxString m_textStoredEnums
, 
 126              m_textStoredTypedefs
, 
 127              m_textStoredFunctionComment
; 
 130 // ----------------------------------------------------------------------------- 
 132 // ----------------------------------------------------------------------------- 
 134 // ============================================================================= 
 136 // ============================================================================= 
 138 int main(int argc
, char **argv
) 
 141         wxLogError("usage: %s <header files...>\n", argv
[0]); 
 147     wxLog::GetActiveTarget()->SetVerbose(); 
 149     // create a parser object and a visitor derivation 
 150     CJSourceParser parser
; 
 151     HelpGenVisitor visitor
; 
 154     for ( int i 
= 1; i 
< argc
; i
++ ) { 
 155         spContext 
*ctxTop 
= parser
.ParseFile(argv
[i
]); 
 157             wxLogWarning("File '%s' couldn't be processed.", argv
[i
]); 
 160             ((spFile 
*)ctxTop
)->mFileName 
= argv
[i
]; 
 161             visitor
.VisitAll(*ctxTop
); 
 169 // ----------------------------------------------------------------------------- 
 170 // HelpGenVisitor implementation 
 171 // ----------------------------------------------------------------------------- 
 173 HelpGenVisitor::HelpGenVisitor() 
 178 void HelpGenVisitor::Reset() 
 183     m_inMethodSection 
= false; 
 186 void HelpGenVisitor::InsertTypedefDocs() 
 188     m_file
.WriteTeX(m_textStoredTypedefs
); 
 189     m_textStoredTypedefs
.Empty(); 
 192 void HelpGenVisitor::InsertEnumDocs() 
 194     m_file
.WriteTeX(m_textStoredEnums
); 
 195     m_textStoredEnums
.Empty(); 
 198 void HelpGenVisitor::InsertDataStructuresHeader() 
 200     if ( !m_inTypesSection 
) { 
 201         m_inTypesSection 
= true; 
 203         m_file
.WriteTeX("\\wxheading{Data structures}\n\n"); 
 207 void HelpGenVisitor::InsertMethodsHeader() 
 209     if ( !m_inMethodSection 
) { 
 210         m_inMethodSection 
= true; 
 212         m_file
.WriteTeX( "\\latexignore{\\rtfignore{\\wxheading{Members}}}\n\n"); 
 216 void HelpGenVisitor::CloseFunction() 
 218     if ( m_inFunction 
) { 
 219         m_inFunction 
= false; 
 222         if ( m_isFirstParam 
) { 
 224             totalText 
<< "\\void"; 
 227         totalText 
<< "}\n\n"; 
 229         if ( !m_textStoredFunctionComment
.IsEmpty() ) 
 230             totalText 
<< m_textStoredFunctionComment 
<< '\n'; 
 232         m_file
.WriteTeX(totalText
); 
 236 void HelpGenVisitor::EndVisit() 
 241 void HelpGenVisitor::VisitFile( spFile
& file 
) 
 243     wxLogInfo("Parsing classes from file '%s'...", file
.mFileName
.c_str()); 
 246 void HelpGenVisitor::VisitClass( spClass
& cl 
) 
 248     wxString name 
= cl
.GetName(); 
 250     // the file name is built from the class name by removing the leading "wx" 
 251     // if any and converting it to the lower case 
 252     wxString filename 
= name
; 
 253     if ( filename(0, 2) == "wx" ) { 
 254         filename
.erase(0, 2); 
 257     filename
.MakeLower(); 
 260     m_inClass 
= m_file
.Open(filename
, wxFile::write
); 
 262         wxLogError("Can't generate documentation for the class '%s'.", 
 269     m_inTypesSection 
= false; 
 271     wxLogInfo("Created new file '%s' for class '%s'.", 
 272               filename
.c_str(), name
.c_str()); 
 274     // the entire text we're writing to file 
 277     // write out the header 
 279         time_t timeNow 
= time(NULL
); 
 281         header
.Printf("% automatically generated by HelpGen from %s at " 
 282                       "%s" // no '\n' here because ctime() inserts one 
 283                       "\\section{\\class{%s}}\\label{%s}\n", 
 284                       filename
.c_str(), ctime(&timeNow
), 
 285                       name
.c_str(), wxString(name
).MakeLower().c_str()); 
 287         totalText 
<< header 
<< '\n'; 
 290     // the comment before the class generally explains what is it for so put it 
 291     // in place of the class description 
 292     if ( cl
.HasComments() ) { 
 294         const MCommentListT
& comments 
= cl
.GetCommentList(); 
 295         for ( MCommentListT::const_iterator i 
= comments
.begin(); 
 298             comment 
<< (*i
)->GetText(); 
 301         totalText 
<< '\n' << comment 
<< '\n'; 
 304     // derived from section 
 305     wxString derived 
= "\\wxheading{Derived from}\n\n"; 
 307     const StrListT
& baseClasses 
= cl
.mSuperClassNames
; 
 308     if ( baseClasses
.size() == 0 ) { 
 309         derived 
<< "No base class"; 
 313         for ( StrListT::const_iterator i 
= baseClasses
.begin(); 
 314               i 
!= baseClasses
.end(); 
 317                 // separate from the previous one 
 324             wxString baseclass 
= *i
; 
 325             derived 
<< "\\helpref{" << baseclass 
<< "}" 
 326                        "{ " << baseclass
.MakeLower()  << "}"; 
 329     totalText 
<< derived 
<< "\n\n"; 
 331     // write all this to file 
 332     m_file
.WriteTeX(totalText
); 
 334     // if there were any enums/typedefs before, insert their documentation now 
 335     InsertDataStructuresHeader(); 
 340 void HelpGenVisitor::VisitEnumeration( spEnumeration
& en 
) 
 344     if ( m_inMethodSection 
) { 
 345         // FIXME that's a bug, but tell the user aboit it nevertheless... we 
 346         // should be smart enough to process even the enums which come after the 
 348         wxLogWarning("enum '%s' ignored, please put it before the class " 
 349                      "methods.", en
.GetName().c_str()); 
 353     // simply copy the enum text in the docs 
 354     wxString enumeration
; 
 355     enumeration 
<< "{\\small \\begin{verbatim}\n" 
 357                 << "\n\\end{verbatim}}\n"; 
 359     // remember for later use if we're not inside a class yet 
 361         if ( !m_textStoredEnums
.IsEmpty() ) { 
 362             m_textStoredEnums 
<< '\n'; 
 365         m_textStoredEnums 
<< enumeration
; 
 368         // write the header for this section if not done yet 
 369         InsertDataStructuresHeader(); 
 372         m_file
.WriteTeX(enumeration
); 
 376 void HelpGenVisitor::VisitTypeDef( spTypeDef
& td 
) 
 380     wxFAIL_MSG("don't know how to document typedefs yet"); 
 383 void HelpGenVisitor::VisitAttribute( spAttribute
& attr 
) 
 387     // only document the public member variables 
 388     if ( !m_inClass 
|| !attr
.IsPublic() ) 
 391     wxFAIL_MSG("don't know how to document member vars yet"); 
 394 void HelpGenVisitor::VisitOperation( spOperation
& op 
) 
 398     if ( !m_inClass 
|| !op
.IsInClass() ) { 
 399         // FIXME that's a bug too 
 400         wxLogWarning("skipped global function '%s'.", op
.GetName().c_str()); 
 405     if ( op
.mVisibility 
== SP_VIS_PRIVATE 
) { 
 406         // FIXME should we document protected functions? 
 410     InsertMethodsHeader(); 
 414     m_isFirstParam 
= true; 
 416     m_textStoredFunctionComment
.Empty(); 
 417     const MCommentListT
& comments 
= op
.GetCommentList(); 
 418     for ( MCommentListT::const_iterator i 
= comments
.begin(); 
 421         m_textStoredFunctionComment 
<< (*i
)->GetText(); 
 424     // start function documentation 
 426     const char *funcname 
= op
.GetName().c_str(); 
 427     const char *classname 
= op
.GetClass().GetName().c_str(); 
 429     // check for the special case of dtor 
 431     if ( (funcname
[0] == '~') && (strcmp(funcname 
+ 1, classname
) == 0) ) { 
 432         dtor
.Printf("\\destruct{%s}", classname
); 
 436     totalText
.Printf("\\membersection{%s::%s}\\label{%s}\n" 
 439                      MakeLabel(classname
, funcname
).c_str(), 
 440                      op
.mIsConstant 
? "const" : "", 
 444     m_file
.WriteTeX(totalText
); 
 447 void HelpGenVisitor::VisitParameter( spParameter
& param 
) 
 453     if ( m_isFirstParam 
) { 
 454         m_isFirstParam 
= false; 
 460     totalText 
<< "\\param{" << param
.mType 
<< " }{" << param
.GetName(); 
 461     wxString defvalue 
= param
.mInitVal
; 
 462     if ( !defvalue
.IsEmpty() ) { 
 463         totalText 
<< " = " << defvalue
; 
 468     m_file
.WriteTeX(totalText
); 
 471 // ----------------------------------------------------------------------------- 
 472 // global function implementation 
 473 // ----------------------------------------------------------------------------- 
 475 static wxString 
MakeLabel(const char *classname
, const char *funcname
) 
 477     wxString 
label(classname
); 
 478     if ( funcname
[0] == '\\' ) { 
 479         // we may have some special TeX macro - so far only \destruct exists, 
 480         // but may be later others will be added 
 481         static const char *macros
[] = { "destruct" }; 
 482         static const char *replacement
[] = { "dtor" }; 
 485         for ( n 
= 0; n 
< WXSIZEOF(macros
); n
++ ) { 
 486             if ( strncmp(funcname 
+ 1, macros
[n
], strlen(macros
[n
])) == 0 ) { 
 492         if ( n 
== WXSIZEOF(macros
) ) { 
 493             wxLogWarning("unknown function name '%s' - leaving as is.", 
 497             funcname 
= replacement
[n
]; 
 508 static void TeXFilter(wxString
* str
) 
 510     // FIXME may be done much more quickly 
 511     str
->Replace("&", "\\&"); 
 512     str
->Replace("_", "\\_"); 
 515 /* vi: set tw=80 et ts=4 sw=4: */