]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/HelpGen/src/HelpGen.cpp
Added more makefiles
[wxWidgets.git] / utils / HelpGen / src / HelpGen.cpp
index af3023ecdfbb415d3e89bddf5120f7cc52d3aacb..28f36a2f0185a8a86e6f5d5d109863ec21455c74 100644 (file)
     2. Document typedefs
     3. Document global variables
     4. Document #defines
+   +5. Program options
 
    (ii) plans for version 2
     1. Use wxTextFile for direct file access to avoid one scan method problems
+    2. Use command line parsrer class for the options
    
 */
 
 #ifndef WX_PRECOMP
     #include <wx/string.h>
     #include <wx/log.h>
-    #include <wx/file.h>
+    #include <wx/dynarray.h>
 #endif // WX_PRECOMP
 
+#include <wx/file.h>
+
 // C++ parsing classes
 #include "cjparser.h"
 
 // private functions
 // -----------------------------------------------------------------------------
 
-// return the label for the given function name
-static wxString MakeLabel(const char *classname, const char *funcname);
-    
+// return the label for the given function name (i.e. argument of \label)
+static wxString MakeLabel(const char *classname, const char *funcname = NULL);
+
+// return the whole \helpref{arg}{arg_label} string
+static wxString MakeHelpref(const char *argument);
+
 // quotes special TeX characters in place
 static void TeXFilter(wxString* str);
 
+// get all comments associated with this context
+static wxString GetAllComments(const spContext& ctx);
+
+// get the string with current time (returns pointer to static buffer)
+// timeFormat is used for the call of strftime(3)
+#ifdef GetCurrentTime
+#undef GetCurrentTime
+#endif
+
+static const char *GetCurrentTime(const char *timeFormat);
+
 // -----------------------------------------------------------------------------
 // private classes
 // -----------------------------------------------------------------------------
@@ -87,6 +105,7 @@ public:
     virtual void VisitClass( spClass& cl );
     virtual void VisitEnumeration( spEnumeration& en );
     virtual void VisitTypeDef( spTypeDef& td );
+       virtual void VisitPreprocessorLine( spPreprocessorLine& pd );
     virtual void VisitAttribute( spAttribute& attr );
     virtual void VisitOperation( spOperation& op );
     virtual void VisitParameter( spParameter& param );
@@ -125,6 +144,9 @@ protected:
     wxString m_textStoredEnums,
              m_textStoredTypedefs,
              m_textStoredFunctionComment;
+
+    // headers included by this file             
+    wxArrayString m_headers;
 };
 
 // -----------------------------------------------------------------------------
@@ -135,23 +157,44 @@ protected:
 // implementation
 // =============================================================================
 
+// this function never returns
+static void usage()
+{
+    wxLogError("usage: HelpGen [-q|-v] <header files...>\n");
+
+    exit(1);
+}
+
 int main(int argc, char **argv)
 {
     if ( argc < 2 ) {
-        wxLogError("usage: %s <header files...>\n", argv[0]);
-
-        return 1;
+        usage();
     }
 
-    // be verbose
-    wxLog::GetActiveTarget()->SetVerbose();
+    int first;
+    for ( first = 1; (first < argc) && argv[first][0] == '-'; first++ ) {
+        switch ( argv[first][1] ) {
+            case 'v':
+                // be verbose
+                wxLog::GetActiveTarget()->SetVerbose();
+                break;
+
+            case 'q':
+                // be quiet
+                wxLog::GetActiveTarget()->SetVerbose(false);
+                break;
+
+            default:
+                usage();
+        }
+    }
 
     // create a parser object and a visitor derivation
     CJSourceParser parser;
     HelpGenVisitor visitor;
 
     // parse all files
-    for ( int i = 1; i < argc; i++ ) {
+    for ( int i = first; i < argc; i++ ) {
         spContext *ctxTop = parser.ParseFile(argv[i]);
         if ( !ctxTop ) {
             wxLogWarning("File '%s' couldn't be processed.", argv[i]);
@@ -181,6 +224,11 @@ void HelpGenVisitor::Reset()
     m_inFunction =
     m_inTypesSection =
     m_inMethodSection = false;
+
+    m_textStoredTypedefs =
+    m_textStoredEnums =
+    m_textStoredFunctionComment = "";
+    m_headers.Empty();
 }
 
 void HelpGenVisitor::InsertTypedefDocs()
@@ -236,11 +284,15 @@ void HelpGenVisitor::CloseFunction()
 void HelpGenVisitor::EndVisit()
 {
     CloseFunction();
+
+    wxLogInfo("%s: finished parsing the current file.",
+              GetCurrentTime("%H:%M:%S"));
 }
 
 void HelpGenVisitor::VisitFile( spFile& file )
 {
-    wxLogInfo("Parsing classes from file '%s'...", file.mFileName.c_str());
+    wxLogInfo("%s: started to parse classes from file '%s'...",
+              GetCurrentTime("%H:%M:%S"), file.mFileName.c_str());
 }
 
 void HelpGenVisitor::VisitClass( spClass& cl )
@@ -276,27 +328,82 @@ void HelpGenVisitor::VisitClass( spClass& cl )
 
     // write out the header
     {
-        time_t timeNow = time(NULL);
         wxString header;
-        header.Printf("% automatically generated by HelpGen from %s at "
-                      "%s" // no '\n' here because ctime() inserts one
+        header.Printf("% automatically generated by HelpGen from %s at %s\n"
                       "\\section{\\class{%s}}\\label{%s}\n",
-                      filename.c_str(), ctime(&timeNow),
+                      filename.c_str(), GetCurrentTime("%d/%b/%y %H:%M:%S"),
                       name.c_str(), wxString(name).MakeLower().c_str());
 
         totalText << header << '\n';
     }
 
+    // if the header includes other headers they must be related to it... try to
+    // automatically generate the "See also" clause
+    if ( !m_headers.IsEmpty() ) {
+        // correspondence between wxWindows headers and class names
+        static const char *headers[] = {
+            "object",
+            "defs",
+            "string",
+            "dynarray",
+            "file",    
+            "time",
+        };
+
+        // NULL here means not to insert anything in "See also" for the
+        // corresponding header
+        static const char *classes[] = {
+            NULL,
+            NULL,
+            NULL,
+            NULL,
+            "wxFile",
+            "wxTime",
+        };
+
+        wxASSERT_MSG( WXSIZEOF(headers) == WXSIZEOF(classes),
+                      "arrays must be in sync!" );
+
+        wxArrayInt interestingClasses;
+
+        size_t count = m_headers.Count(), index;
+        for ( size_t n = 0; n < count; n++ ) {
+            wxString baseHeaderName = m_headers[n].Before('.');
+            if ( baseHeaderName(0, 3) != "wx/" )
+                continue;
+
+            baseHeaderName.erase(0, 3);
+            for ( index = 0; index < WXSIZEOF(headers); index++ ) {
+                if ( Stricmp(baseHeaderName, headers[index]) == 0 )
+                    break;
+            }
+
+            if ( (index < WXSIZEOF(headers)) && classes[index] ) {
+                // interesting header
+                interestingClasses.Add(index);
+            }
+        }
+
+        if ( !interestingClasses.IsEmpty() ) {
+            // do generate "See also" clause
+            totalText << "\\wxheading{See also:}\n\n";
+
+            count = interestingClasses.Count();
+            for ( index = 0; index < count; index++ ) {
+                if ( index > 0 )
+                    totalText << ", ";
+
+                totalText << MakeHelpref(classes[interestingClasses[index]]);
+            }
+
+            totalText << "\n\n";
+        }
+    }
+
     // the comment before the class generally explains what is it for so put it
     // in place of the class description
     if ( cl.HasComments() ) {
-        wxString comment;
-        const MCommentListT& comments = cl.GetCommentList();
-        for ( MCommentListT::const_iterator i = comments.begin();
-              i != comments.end();
-              i++ ) {
-            comment << (*i)->GetText();
-        }
+        wxString comment = GetAllComments(cl);
 
         totalText << '\n' << comment << '\n';
     }
@@ -322,8 +429,8 @@ void HelpGenVisitor::VisitClass( spClass& cl )
             }
 
             wxString baseclass = *i;
-            derived << "\\helpref{" << baseclass << "}"
-                       "{ " << baseclass.MakeLower()  << "}";
+            derived << "\\helpref{" << baseclass << "}";
+                       derived << "{" << baseclass.MakeLower()  << "}";
         }
     }
     totalText << derived << "\n\n";
@@ -351,7 +458,7 @@ void HelpGenVisitor::VisitEnumeration( spEnumeration& en )
     }
 
     // simply copy the enum text in the docs
-    wxString enumeration;
+    wxString enumeration = GetAllComments(en);
     enumeration << "{\\small \\begin{verbatim}\n"
                 << en.mEnumContent
                 << "\n\\end{verbatim}}\n";
@@ -377,7 +484,47 @@ void HelpGenVisitor::VisitTypeDef( spTypeDef& td )
 {
     CloseFunction();
 
-    wxFAIL_MSG("don't know how to document typedefs yet");
+    if ( m_inMethodSection ) {
+        // FIXME that's a bug, but tell the user aboit it nevertheless...
+        wxLogWarning("typedef '%s' ignored, please put it before the class "
+                     "methods.", td.GetName().c_str());
+        return;
+    }
+
+    wxString typedefdoc;
+    typedefdoc << "{\\small \\begin{verbatim}\n"
+               << "typedef " << td.mOriginalType << ' ' << td.GetName()
+               << "\n\\end{verbatim}}\n"
+               << GetAllComments(td);
+
+    // remember for later use if we're not inside a class yet
+    if ( !m_inClass ) {
+        if ( !m_textStoredTypedefs.IsEmpty() ) {
+            m_textStoredTypedefs << '\n';
+        }
+
+        m_textStoredTypedefs << typedefdoc;
+    }
+    else {
+        // write the header for this section if not done yet
+        InsertDataStructuresHeader();
+
+        typedefdoc << '\n';
+        m_file.WriteTeX(typedefdoc);
+    }
+}
+
+void HelpGenVisitor::VisitPreprocessorLine( spPreprocessorLine& pd )
+{
+    switch ( pd.GetStatementType() ) {
+        case SP_PREP_DEF_INCLUDE_FILE:
+            m_headers.Add(pd.CPP_GetIncludedFileNeme());
+            break;
+
+        case SP_PREP_DEF_DEFINE_SYMBOL:
+            // TODO decide if it's a constant and document it if it is
+            break;
+    }
 }
 
 void HelpGenVisitor::VisitAttribute( spAttribute& attr )
@@ -388,7 +535,7 @@ void HelpGenVisitor::VisitAttribute( spAttribute& attr )
     if ( !m_inClass || !attr.IsPublic() )
         return;
 
-    wxFAIL_MSG("don't know how to document member vars yet");
+    wxLogWarning("Ignoring member variable '%s'.", attr.GetName().c_str());
 }
 
 void HelpGenVisitor::VisitOperation( spOperation& op )
@@ -413,13 +560,7 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
     m_inFunction =
     m_isFirstParam = true;
 
-    m_textStoredFunctionComment.Empty();
-    const MCommentListT& comments = op.GetCommentList();
-    for ( MCommentListT::const_iterator i = comments.begin();
-          i != comments.end();
-          i++ ) {
-        m_textStoredFunctionComment << (*i)->GetText();
-    }
+    m_textStoredFunctionComment = GetAllComments(op);
 
     // start function documentation
     wxString totalText;
@@ -433,11 +574,12 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
         funcname = dtor;
     }
 
-    totalText.Printf("\\membersection{%s::%s}\\label{%s}\n"
-                     "\\%sfunc{%s}{%s}{",
+    totalText.Printf("\\membersection{%s::%s}\\label{%s}\n\n"
+                     "\\%sfunc{%s%s}{%s}{",
                      classname, funcname,
                      MakeLabel(classname, funcname).c_str(),
                      op.mIsConstant ? "const" : "",
+                     op.mIsVirtual ? "virtual " : "",
                      op.mRetType.c_str(),
                      funcname);
 
@@ -475,7 +617,7 @@ void HelpGenVisitor::VisitParameter( spParameter& param )
 static wxString MakeLabel(const char *classname, const char *funcname)
 {
     wxString label(classname);
-    if ( funcname[0] == '\\' ) {
+    if ( funcname && funcname[0] == '\\' ) {
         // we may have some special TeX macro - so far only \destruct exists,
         // but may be later others will be added
         static const char *macros[] = { "destruct" };
@@ -498,13 +640,22 @@ static wxString MakeLabel(const char *classname, const char *funcname)
         }
     }
 
-    label << funcname;
+    if ( funcname )
+        label << funcname;
 
     label.MakeLower();
 
     return label;
 }
 
+static wxString MakeHelpref(const char *argument)
+{
+    wxString helpref;
+    helpref << "\\helpref{" << argument << "}{" << MakeLabel(argument) << '}';
+
+    return helpref;
+}
+
 static void TeXFilter(wxString* str)
 {
     // FIXME may be done much more quickly
@@ -512,4 +663,31 @@ static void TeXFilter(wxString* str)
     str->Replace("_", "\\_");
 }
 
+static wxString GetAllComments(const spContext& ctx)
+{
+    wxString comment;
+    const MCommentListT& comments = ctx.GetCommentList();
+    for ( MCommentListT::const_iterator i = comments.begin();
+            i != comments.end();
+            i++ ) {
+        comment << (*i)->GetText();
+    }
+
+    return comment;
+}
+
+static const char *GetCurrentTime(const char *timeFormat)
+{
+    static char s_timeBuffer[128];
+    time_t timeNow;
+    struct tm *ptmNow;
+
+    time(&timeNow);
+    ptmNow = localtime(&timeNow);
+
+    strftime(s_timeBuffer, WXSIZEOF(s_timeBuffer), timeFormat, ptmNow);
+
+    return s_timeBuffer;
+}
+
 /* vi: set tw=80 et ts=4 sw=4: */