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/log.cpp\
src/wx/file.cpp\
src/wx/dynarray.cpp\
src/wx/list.cpp
OBJS = obj/cjparser.o\
@ -45,6 +46,7 @@ OBJS = obj/cjparser.o\
obj/wx/hash.o\
obj/wx/log.o\
obj/wx/file.o\
obj/wx/dynarray.o\
obj/wx/list.o
# 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
# this might not work with some versions of gcc - try just -g then
DEBUG = -ggdb
DEBUG = -ggdb -D__WXDEBUG__
INCLUDE = -I./include
CPPFLAGS = $(INCLUDE) $(DEFINES) $(DEBUG) -c -Wall
@ -64,7 +66,7 @@ CPPFLAGS = $(INCLUDE) $(DEFINES) $(DEBUG) -c -Wall
obj/%.o: src/%.cpp
$(CC) $(CPPFLAGS) -o $@ $<
all: links $(PROG)
all: $(PROG)
$(PROG) : $(OBJS)
$(CC) -o $(PROG) $(DEBUG) -Wall $(OBJS)

View File

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

View File

@ -18,9 +18,11 @@
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
*/
@ -39,6 +41,7 @@
#include <wx/string.h>
#include <wx/log.h>
#include <wx/file.h>
#include <wx/dynarray.h>
#endif // WX_PRECOMP
// C++ parsing classes
@ -52,12 +55,22 @@
// 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)
static const char *GetCurrentTime(const char *timeFormat);
// -----------------------------------------------------------------------------
// private classes
// -----------------------------------------------------------------------------
@ -87,6 +100,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 +139,9 @@ protected:
wxString m_textStoredEnums,
m_textStoredTypedefs,
m_textStoredFunctionComment;
// headers included by this file
wxArrayString m_headers;
};
// -----------------------------------------------------------------------------
@ -135,23 +152,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 +219,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 +279,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 +323,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';
}
@ -351,7 +453,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 +479,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 +530,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 +555,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;
@ -434,10 +570,11 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
}
totalText.Printf("\\membersection{%s::%s}\\label{%s}\n"
"\\%sfunc{%s}{%s}{",
"\\%sfunc{%s%s}{%s}{",
classname, funcname,
MakeLabel(classname, funcname).c_str(),
op.mIsConstant ? "const" : "",
op.mIsVirtual ? "virtual " : "",
op.mRetType.c_str(),
funcname);
@ -475,7 +612,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 +635,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 +658,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: */