supports typedefs, generates "See also:" and adds "virtual " for virtual

functions


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1348 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-01-08 19:46:24 +00:00
parent cecfc5e7e5
commit ed38ec7e34
3 changed files with 213 additions and 38 deletions

View File

@@ -30,6 +30,7 @@ SRCS = src/cjparser.cpp\
src/wx/hash.cpp\ src/wx/hash.cpp\
src/wx/log.cpp\ src/wx/log.cpp\
src/wx/file.cpp\ src/wx/file.cpp\
src/wx/dynarray.cpp\
src/wx/list.cpp src/wx/list.cpp
OBJS = obj/cjparser.o\ OBJS = obj/cjparser.o\
@@ -45,6 +46,7 @@ OBJS = obj/cjparser.o\
obj/wx/hash.o\ obj/wx/hash.o\
obj/wx/log.o\ obj/wx/log.o\
obj/wx/file.o\ obj/wx/file.o\
obj/wx/dynarray.o\
obj/wx/list.o obj/wx/list.o
# tested with egcs 1.1.1 (add more compilers here) # tested with egcs 1.1.1 (add more compilers here)
@@ -52,7 +54,7 @@ CC = g++
DEFINES = -DwxUSE_NOGUI=1 -D__UNIX__ -D__WXGTK__ -DHAVE_VSNPRINTF DEFINES = -DwxUSE_NOGUI=1 -D__UNIX__ -D__WXGTK__ -DHAVE_VSNPRINTF
# this might not work with some versions of gcc - try just -g then # this might not work with some versions of gcc - try just -g then
DEBUG = -ggdb DEBUG = -ggdb -D__WXDEBUG__
INCLUDE = -I./include INCLUDE = -I./include
CPPFLAGS = $(INCLUDE) $(DEFINES) $(DEBUG) -c -Wall CPPFLAGS = $(INCLUDE) $(DEFINES) $(DEBUG) -c -Wall
@@ -64,7 +66,7 @@ CPPFLAGS = $(INCLUDE) $(DEFINES) $(DEBUG) -c -Wall
obj/%.o: src/%.cpp obj/%.o: src/%.cpp
$(CC) $(CPPFLAGS) -o $@ $< $(CC) $(CPPFLAGS) -o $@ $<
all: links $(PROG) all: $(PROG)
$(PROG) : $(OBJS) $(PROG) : $(OBJS)
$(CC) -o $(PROG) $(DEBUG) -Wall $(OBJS) $(CC) -o $(PROG) $(DEBUG) -Wall $(OBJS)

View File

@@ -367,8 +367,8 @@ public:
// TRUE, if there is at least one entry // TRUE, if there is at least one entry
// in the comment list of this context // in the comment list of this context
bool HasComments(); bool HasComments();
inline MCommentListT& GetCommentList() MCommentListT& GetCommentList() { return mComments; }
{ return mComments; } const MCommentListT& GetCommentList() const { return mComments; }
// should be overriden, if the context supports sorting // should be overriden, if the context supports sorting
// of it's members // of it's members

View File

@@ -18,9 +18,11 @@
2. Document typedefs 2. Document typedefs
3. Document global variables 3. Document global variables
4. Document #defines 4. Document #defines
+5. Program options
(ii) plans for version 2 (ii) plans for version 2
1. Use wxTextFile for direct file access to avoid one scan method problems 1. Use wxTextFile for direct file access to avoid one scan method problems
2. Use command line parsrer class for the options
*/ */
@@ -39,6 +41,7 @@
#include <wx/string.h> #include <wx/string.h>
#include <wx/log.h> #include <wx/log.h>
#include <wx/file.h> #include <wx/file.h>
#include <wx/dynarray.h>
#endif // WX_PRECOMP #endif // WX_PRECOMP
// C++ parsing classes // C++ parsing classes
@@ -52,12 +55,22 @@
// private functions // private functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// return the label for the given function name // return the label for the given function name (i.e. argument of \label)
static wxString MakeLabel(const char *classname, const char *funcname); 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 // quotes special TeX characters in place
static void TeXFilter(wxString* str); 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)
static const char *GetCurrentTime(const char *timeFormat);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// private classes // private classes
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -87,6 +100,7 @@ public:
virtual void VisitClass( spClass& cl ); virtual void VisitClass( spClass& cl );
virtual void VisitEnumeration( spEnumeration& en ); virtual void VisitEnumeration( spEnumeration& en );
virtual void VisitTypeDef( spTypeDef& td ); virtual void VisitTypeDef( spTypeDef& td );
virtual void VisitPreprocessorLine( spPreprocessorLine& pd );
virtual void VisitAttribute( spAttribute& attr ); virtual void VisitAttribute( spAttribute& attr );
virtual void VisitOperation( spOperation& op ); virtual void VisitOperation( spOperation& op );
virtual void VisitParameter( spParameter& param ); virtual void VisitParameter( spParameter& param );
@@ -125,6 +139,9 @@ protected:
wxString m_textStoredEnums, wxString m_textStoredEnums,
m_textStoredTypedefs, m_textStoredTypedefs,
m_textStoredFunctionComment; m_textStoredFunctionComment;
// headers included by this file
wxArrayString m_headers;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -135,23 +152,44 @@ protected:
// implementation // implementation
// ============================================================================= // =============================================================================
// this function never returns
static void usage()
{
wxLogError("usage: HelpGen [-q|-v] <header files...>\n");
exit(1);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if ( argc < 2 ) { if ( argc < 2 ) {
wxLogError("usage: %s <header files...>\n", argv[0]); usage();
return 1;
} }
// be verbose int first;
wxLog::GetActiveTarget()->SetVerbose(); 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 // create a parser object and a visitor derivation
CJSourceParser parser; CJSourceParser parser;
HelpGenVisitor visitor; HelpGenVisitor visitor;
// parse all files // parse all files
for ( int i = 1; i < argc; i++ ) { for ( int i = first; i < argc; i++ ) {
spContext *ctxTop = parser.ParseFile(argv[i]); spContext *ctxTop = parser.ParseFile(argv[i]);
if ( !ctxTop ) { if ( !ctxTop ) {
wxLogWarning("File '%s' couldn't be processed.", argv[i]); wxLogWarning("File '%s' couldn't be processed.", argv[i]);
@@ -181,6 +219,11 @@ void HelpGenVisitor::Reset()
m_inFunction = m_inFunction =
m_inTypesSection = m_inTypesSection =
m_inMethodSection = false; m_inMethodSection = false;
m_textStoredTypedefs =
m_textStoredEnums =
m_textStoredFunctionComment = "";
m_headers.Empty();
} }
void HelpGenVisitor::InsertTypedefDocs() void HelpGenVisitor::InsertTypedefDocs()
@@ -236,11 +279,15 @@ void HelpGenVisitor::CloseFunction()
void HelpGenVisitor::EndVisit() void HelpGenVisitor::EndVisit()
{ {
CloseFunction(); CloseFunction();
wxLogInfo("%s: finished parsing the current file.",
GetCurrentTime("%H:%M:%S"));
} }
void HelpGenVisitor::VisitFile( spFile& file ) 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 ) void HelpGenVisitor::VisitClass( spClass& cl )
@@ -276,27 +323,82 @@ void HelpGenVisitor::VisitClass( spClass& cl )
// write out the header // write out the header
{ {
time_t timeNow = time(NULL);
wxString header; wxString header;
header.Printf("% automatically generated by HelpGen from %s at " header.Printf("% automatically generated by HelpGen from %s at %s\n"
"%s" // no '\n' here because ctime() inserts one
"\\section{\\class{%s}}\\label{%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()); name.c_str(), wxString(name).MakeLower().c_str());
totalText << header << '\n'; 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 // the comment before the class generally explains what is it for so put it
// in place of the class description // in place of the class description
if ( cl.HasComments() ) { if ( cl.HasComments() ) {
wxString comment; wxString comment = GetAllComments(cl);
const MCommentListT& comments = cl.GetCommentList();
for ( MCommentListT::const_iterator i = comments.begin();
i != comments.end();
i++ ) {
comment << (*i)->GetText();
}
totalText << '\n' << comment << '\n'; totalText << '\n' << comment << '\n';
} }
@@ -351,7 +453,7 @@ void HelpGenVisitor::VisitEnumeration( spEnumeration& en )
} }
// simply copy the enum text in the docs // simply copy the enum text in the docs
wxString enumeration; wxString enumeration = GetAllComments(en);
enumeration << "{\\small \\begin{verbatim}\n" enumeration << "{\\small \\begin{verbatim}\n"
<< en.mEnumContent << en.mEnumContent
<< "\n\\end{verbatim}}\n"; << "\n\\end{verbatim}}\n";
@@ -377,7 +479,47 @@ void HelpGenVisitor::VisitTypeDef( spTypeDef& td )
{ {
CloseFunction(); 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 ) void HelpGenVisitor::VisitAttribute( spAttribute& attr )
@@ -388,7 +530,7 @@ void HelpGenVisitor::VisitAttribute( spAttribute& attr )
if ( !m_inClass || !attr.IsPublic() ) if ( !m_inClass || !attr.IsPublic() )
return; 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 ) void HelpGenVisitor::VisitOperation( spOperation& op )
@@ -413,13 +555,7 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
m_inFunction = m_inFunction =
m_isFirstParam = true; m_isFirstParam = true;
m_textStoredFunctionComment.Empty(); m_textStoredFunctionComment = GetAllComments(op);
const MCommentListT& comments = op.GetCommentList();
for ( MCommentListT::const_iterator i = comments.begin();
i != comments.end();
i++ ) {
m_textStoredFunctionComment << (*i)->GetText();
}
// start function documentation // start function documentation
wxString totalText; wxString totalText;
@@ -434,10 +570,11 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
} }
totalText.Printf("\\membersection{%s::%s}\\label{%s}\n" totalText.Printf("\\membersection{%s::%s}\\label{%s}\n"
"\\%sfunc{%s}{%s}{", "\\%sfunc{%s%s}{%s}{",
classname, funcname, classname, funcname,
MakeLabel(classname, funcname).c_str(), MakeLabel(classname, funcname).c_str(),
op.mIsConstant ? "const" : "", op.mIsConstant ? "const" : "",
op.mIsVirtual ? "virtual " : "",
op.mRetType.c_str(), op.mRetType.c_str(),
funcname); funcname);
@@ -475,7 +612,7 @@ void HelpGenVisitor::VisitParameter( spParameter& param )
static wxString MakeLabel(const char *classname, const char *funcname) static wxString MakeLabel(const char *classname, const char *funcname)
{ {
wxString label(classname); wxString label(classname);
if ( funcname[0] == '\\' ) { if ( funcname && funcname[0] == '\\' ) {
// we may have some special TeX macro - so far only \destruct exists, // we may have some special TeX macro - so far only \destruct exists,
// but may be later others will be added // but may be later others will be added
static const char *macros[] = { "destruct" }; static const char *macros[] = { "destruct" };
@@ -498,13 +635,22 @@ static wxString MakeLabel(const char *classname, const char *funcname)
} }
} }
label << funcname; if ( funcname )
label << funcname;
label.MakeLower(); label.MakeLower();
return label; return label;
} }
static wxString MakeHelpref(const char *argument)
{
wxString helpref;
helpref << "\\helpref{" << argument << "}{" << MakeLabel(argument) << '}';
return helpref;
}
static void TeXFilter(wxString* str) static void TeXFilter(wxString* str)
{ {
// FIXME may be done much more quickly // FIXME may be done much more quickly
@@ -512,4 +658,31 @@ static void TeXFilter(wxString* str)
str->Replace("_", "\\_"); 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: */ /* vi: set tw=80 et ts=4 sw=4: */