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:
parent
cecfc5e7e5
commit
ed38ec7e34
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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: */
|
||||
|
Loading…
Reference in New Issue
Block a user