1. more C++ parser fixes - now it almost parses wx/string.h

a) #if/#ifdef/#else (very) limited support
 b) param type fix - now indirection chars are correctly handled
 c) class/struct/union distinction
 d) public/private fixes
 e) Dump() function added - very useful for debugging

2. option to ignore parameter names during 'diff' (in fact, they're ignored
   by default, and this option switches it on)


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1744 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-02-21 22:32:46 +00:00
parent c4c794e1d0
commit d12e353663
6 changed files with 2617 additions and 2197 deletions

View File

@@ -38,6 +38,13 @@
#include "markup.h" // markup tags used in spOperator::GetFullName() #include "markup.h" // markup tags used in spOperator::GetFullName()
// these methods are used for debugging only and disappear in the release build
#ifdef __WXDEBUG__
#define DECLARE_DUMP virtual void DumpThis(const wxString& indent) const;
#else
#define DECLARE_DUMP
#endif
// context class list in "inside-out" order : // context class list in "inside-out" order :
class spContext; class spContext;
@@ -63,6 +70,7 @@ enum SRC_VISIBLITY_TYPES
// class types // class types
enum SP_CLASS_TYPES enum SP_CLASS_TYPES
{ {
SP_CLTYPE_INVALID,
SP_CLTYPE_CLASS, SP_CLTYPE_CLASS,
SP_CLTYPE_TEMPLATE_CLASS, SP_CLTYPE_TEMPLATE_CLASS,
SP_CLTYPE_STRUCTURE, SP_CLTYPE_STRUCTURE,
@@ -445,11 +453,18 @@ public:
// each new context should override this method // each new context should override this method
// to return it's specific type // to return it's specific type
virtual int GetContextType() { return SP_CTX_UNKNOWN; } virtual int GetContextType() const { return SP_CTX_UNKNOWN; }
// perhaps more intuitive short-cut // perhaps more intuitive short-cut
inline int GetType() { return GetContextType(); } inline int GetType() { return GetContextType(); }
// cast this context to the desired type - returns NULL if type is wrong
spAttribute *CastToAttribute()
{
return GetContextType() == SP_CTX_ATTRIBUTE ? (spAttribute *)this
: NULL;
}
// derived classes override this to invoke VisitXXX method // derived classes override this to invoke VisitXXX method
// which corresponds to the class of specific context, // which corresponds to the class of specific context,
// - this is what the "Visitor" pattern told us ^) // - this is what the "Visitor" pattern told us ^)
@@ -468,6 +483,12 @@ public:
void RemoveChildren(); void RemoveChildren();
spContext* GetEnclosingContext( int mask = SP_CTX_ANY ); spContext* GetEnclosingContext( int mask = SP_CTX_ANY );
#ifdef __WXDEBUG__
virtual void Dump(const wxString& indent) const;
#endif // __WXDEBUG__
DECLARE_DUMP
}; };
// stores information about single argument of operation // stores information about single argument of operation
@@ -482,10 +503,12 @@ public:
string mInitVal; string mInitVal;
public: public:
virtual int GetContextType() { return SP_CTX_PARAMETER; } virtual int GetContextType() const { return SP_CTX_PARAMETER; }
virtual void AcceptVisitor( spVisitor& visitor ) virtual void AcceptVisitor( spVisitor& visitor )
{ visitor.VisitParameter( *this ); } { visitor.VisitParameter( *this ); }
DECLARE_DUMP
}; };
@@ -504,10 +527,12 @@ public:
bool mIsConstant; bool mIsConstant;
public: public:
virtual int GetContextType() { return SP_CTX_ATTRIBUTE; } virtual int GetContextType() const { return SP_CTX_ATTRIBUTE; }
virtual void AcceptVisitor( spVisitor& visitor ) virtual void AcceptVisitor( spVisitor& visitor )
{ visitor.VisitAttribute( *this ); } { visitor.VisitAttribute( *this ); }
DECLARE_DUMP
}; };
class spOperation : public spContext class spOperation : public spContext
@@ -554,11 +579,12 @@ public:
virtual string GetFullName(MarkupTagsT tags); virtual string GetFullName(MarkupTagsT tags);
virtual int GetContextType() { return SP_CTX_OPERATION; } virtual int GetContextType() const { return SP_CTX_OPERATION; }
virtual void AcceptVisitor( spVisitor& visitor ) virtual void AcceptVisitor( spVisitor& visitor )
{ visitor.VisitOperation( *this ); } { visitor.VisitOperation( *this ); }
DECLARE_DUMP
}; };
// stores infromation about preprocessor directive // stores infromation about preprocessor directive
@@ -576,14 +602,16 @@ public:
public: public:
virtual int GetContextType() { return SP_CTX_PREPROCESSOR; } virtual int GetContextType() const { return SP_CTX_PREPROCESSOR; }
virtual int GetStatementType() { return mDefType; } virtual int GetStatementType() const { return mDefType; }
string CPP_GetIncludedFileNeme(); string CPP_GetIncludedFileNeme() const;
virtual void AcceptVisitor( spVisitor& visitor ) virtual void AcceptVisitor( spVisitor& visitor )
{ visitor.VisitPreprocessorLine( *this ); } { visitor.VisitPreprocessorLine( *this ); }
DECLARE_DUMP
}; };
// stores information about the class // stores information about the class
@@ -607,7 +635,6 @@ public:
bool mIsAbstract; bool mIsAbstract;
public: public:
// sorts class members in the following order: // sorts class members in the following order:
// //
// (by "privacy level" - first private, than protected, public) // (by "privacy level" - first private, than protected, public)
@@ -622,10 +649,12 @@ public:
virtual void SortMembers(); virtual void SortMembers();
virtual int GetContextType() { return SP_CTX_CLASS; } virtual int GetContextType() const { return SP_CTX_CLASS; }
virtual void AcceptVisitor( spVisitor& visitor ) virtual void AcceptVisitor( spVisitor& visitor )
{ visitor.VisitClass( *this ); } { visitor.VisitClass( *this ); }
DECLARE_DUMP
}; };
// stores information about enum statement // stores information about enum statement
@@ -636,10 +665,12 @@ public:
string mEnumContent; // full-text content of enumeration string mEnumContent; // full-text content of enumeration
public: public:
virtual int GetContextType() { return SP_CTX_ENUMERATION; } virtual int GetContextType() const { return SP_CTX_ENUMERATION; }
virtual void AcceptVisitor( spVisitor& visitor ) virtual void AcceptVisitor( spVisitor& visitor )
{ visitor.VisitEnumeration( *this ); } { visitor.VisitEnumeration( *this ); }
DECLARE_DUMP
}; };
class spTypeDef : public spContext class spTypeDef : public spContext
@@ -650,10 +681,12 @@ public:
string mOriginalType; string mOriginalType;
public: public:
virtual int GetContextType() { return SP_CTX_TYPEDEF; } virtual int GetContextType() const { return SP_CTX_TYPEDEF; }
virtual void AcceptVisitor( spVisitor& visitor ) virtual void AcceptVisitor( spVisitor& visitor )
{ visitor.VisitTypeDef( *this ); } { visitor.VisitTypeDef( *this ); }
DECLARE_DUMP
}; };
// NOTE:: files context may be put to other // NOTE:: files context may be put to other
@@ -668,10 +701,12 @@ public:
string mFileName; string mFileName;
public: public:
virtual int GetContextType() { return SP_CTX_FILE; } virtual int GetContextType() const { return SP_CTX_FILE; }
virtual void AcceptVisitor( spVisitor& visitor ) virtual void AcceptVisitor( spVisitor& visitor )
{ visitor.VisitFile( *this ); } { visitor.VisitFile( *this ); }
DECLARE_DUMP
}; };
//TODO:: comments. //TODO:: comments.

View File

@@ -33,6 +33,7 @@
(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 parser class for the options 2. Use command line parser class for the options
3. support for overloaded functions in diff mode (search for OVER)
(iii) plans for version 3 (iii) plans for version 3
1. Merging with existing files 1. Merging with existing files
@@ -120,15 +121,70 @@ private:
wxTeXFile& operator=(const wxTeXFile&); wxTeXFile& operator=(const wxTeXFile&);
}; };
// helper class which manages the classes and function names to ignore for
// the documentation purposes (used by both HelpGenVisitor and DocManager)
class IgnoreNamesHandler
{
public:
IgnoreNamesHandler() : m_ignore(CompareIgnoreListEntries) { }
~IgnoreNamesHandler() { WX_CLEAR_ARRAY(m_ignore); }
// load file with classes/functions to ignore (add them to the names we
// already have)
bool AddNamesFromFile(const wxString& filename);
// return TRUE if we ignore this function
bool IgnoreMethod(const wxString& classname,
const wxString& funcname) const
{
if ( IgnoreClass(classname) )
return TRUE;
IgnoreListEntry ignore(classname, funcname);
return m_ignore.Index(&ignore) != wxNOT_FOUND;
}
// return TRUE if we ignore this class entirely
bool IgnoreClass(const wxString& classname) const
{
IgnoreListEntry ignore(classname, "");
return m_ignore.Index(&ignore) != wxNOT_FOUND;
}
protected:
struct IgnoreListEntry
{
IgnoreListEntry(const wxString& classname,
const wxString& funcname)
: m_classname(classname), m_funcname(funcname)
{
}
wxString m_classname;
wxString m_funcname; // if empty, ignore class entirely
};
static int CompareIgnoreListEntries(IgnoreListEntry *first,
IgnoreListEntry *second);
// for efficiency, let's sort it
WX_DEFINE_SORTED_ARRAY(IgnoreListEntry *, ArrayNamesToIgnore);
ArrayNamesToIgnore m_ignore;
private:
IgnoreNamesHandler(const IgnoreNamesHandler&);
IgnoreNamesHandler& operator=(const IgnoreNamesHandler&);
};
// visitor implementation which writes all collected data to a .tex file // visitor implementation which writes all collected data to a .tex file
class HelpGenVisitor : public spVisitor class HelpGenVisitor : public spVisitor
{ {
public: public:
// ctor // ctor
HelpGenVisitor(const wxString& directoryOut) : m_directoryOut(directoryOut) HelpGenVisitor(const wxString& directoryOut, bool overwrite);
{
Reset();
}
virtual void VisitFile( spFile& fl ); virtual void VisitFile( spFile& fl );
virtual void VisitClass( spClass& cl ); virtual void VisitClass( spClass& cl );
@@ -141,6 +197,9 @@ public:
void EndVisit(); void EndVisit();
// get our `ignore' object
IgnoreNamesHandler& GetIgnoreHandler() { return m_ignoreNames; }
// shut up g++ warning (ain't it stupid?) // shut up g++ warning (ain't it stupid?)
virtual ~HelpGenVisitor() { } virtual ~HelpGenVisitor() { }
@@ -160,7 +219,9 @@ protected:
// terminate the function documentation if it was started // terminate the function documentation if it was started
void CloseFunction(); void CloseFunction();
wxString m_directoryOut; // directory for the output wxString m_directoryOut, // directory for the output
m_fileHeader; // name of the .h file we parse
bool m_overwrite; // overwrite existing files?
wxTeXFile m_file; // file we're writing to now wxTeXFile m_file; // file we're writing to now
// state variables // state variables
@@ -178,6 +239,10 @@ protected:
// headers included by this file // headers included by this file
wxArrayString m_headers; wxArrayString m_headers;
// ignore handler: tells us which classes to ignore for doc generation
// purposes
IgnoreNamesHandler m_ignoreNames;
private: private:
HelpGenVisitor(const HelpGenVisitor&); HelpGenVisitor(const HelpGenVisitor&);
HelpGenVisitor& operator=(const HelpGenVisitor&); HelpGenVisitor& operator=(const HelpGenVisitor&);
@@ -189,18 +254,18 @@ private:
class DocManager class DocManager
{ {
public: public:
DocManager() : m_ignore(CompareIgnoreListEntries) { } DocManager(bool checkParamNames);
~DocManager(); ~DocManager();
// load file with class names and function names to ignore during diff
bool LoadIgnoreFile(const wxString& filename);
// returns FALSE on failure // returns FALSE on failure
bool ParseTeXFile(const wxString& filename); bool ParseTeXFile(const wxString& filename);
// returns FALSE if there were any differences // returns FALSE if there were any differences
bool DumpDifferences(spContext *ctxTop) const; bool DumpDifferences(spContext *ctxTop) const;
// get our `ignore' object
IgnoreNamesHandler& GetIgnoreHandler() { return m_ignoreNames; }
protected: protected:
// parsing TeX files // parsing TeX files
// ----------------- // -----------------
@@ -242,40 +307,8 @@ protected:
// functions and classes to ignore during diff // functions and classes to ignore during diff
// ------------------------------------------- // -------------------------------------------
struct IgnoreListEntry
{
IgnoreListEntry(const wxString& classname,
const wxString& funcname)
: m_classname(classname), m_funcname(funcname)
{
}
wxString m_classname; IgnoreNamesHandler m_ignoreNames;
wxString m_funcname; // if empty, ignore class entirely
};
static int CompareIgnoreListEntries(IgnoreListEntry *first,
IgnoreListEntry *second);
// for efficiency, let's sort it
WX_DEFINE_SORTED_ARRAY(IgnoreListEntry *, ArrayNamesToIgnore);
ArrayNamesToIgnore m_ignore;
// return TRUE if we ignore this function
bool IgnoreMethod(const wxString& classname,
const wxString& funcname) const
{
IgnoreListEntry ignore(classname, funcname);
return m_ignore.Index(&ignore) != wxNOT_FOUND;
}
// return TRUE if we ignore this class entirely
bool IgnoreClass(const wxString& classname) const
{
return IgnoreMethod(classname, "");
}
// information about all functions documented in the TeX file(s) // information about all functions documented in the TeX file(s)
// ------------------------------------------------------------- // -------------------------------------------------------------
@@ -367,6 +400,13 @@ protected:
// the class name appears in m_classes // the class name appears in m_classes
wxArrayString m_classes; wxArrayString m_classes;
ArrayMethodInfos m_methods; ArrayMethodInfos m_methods;
// are we checking parameter names?
bool m_checkParamNames;
private:
DocManager(const DocManager&);
DocManager& operator=(const DocManager&);
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -397,18 +437,20 @@ static void usage()
" -v be verbose\n" " -v be verbose\n"
" -H give this usage message\n" " -H give this usage message\n"
" -V print the version info\n" " -V print the version info\n"
" -i file file with classes/function to ignore\n"
"\n" "\n"
" where mode is one of: dump, diff\n" " where mode is one of: dump, diff\n"
"\n" "\n"
" dump means generate .tex files for TeX2RTF converter from specified\n" " dump means generate .tex files for TeX2RTF converter from specified\n"
" headers files, mode options are:\n" " headers files, mode options are:\n"
" -f overwrite existing files\n"
" -o outdir directory for generated files\n" " -o outdir directory for generated files\n"
"\n" "\n"
" diff means compare the set of methods documented .tex file with the\n" " diff means compare the set of methods documented .tex file with the\n"
" methods declared in the header:\n" " methods declared in the header:\n"
" %s diff <file.h> <files.tex...>.\n" " %s diff <file.h> <files.tex...>.\n"
" options are:\n" " mode specific options are:\n"
" -i file file with classes/function to ignore during diff\n" " -p do check parameter names (not done by default)\n"
"\n", basename.c_str(), basename.c_str()); "\n", basename.c_str(), basename.c_str());
exit(1); exit(1);
@@ -430,7 +472,10 @@ int main(int argc, char **argv)
} }
wxArrayString filesH, filesTeX; wxArrayString filesH, filesTeX;
wxString directoryOut, ignoreFile; wxString directoryOut, // directory for 'dmup' output
ignoreFile; // file with classes/functions to ignore
bool overwrite = FALSE, // overwrite existing files during 'dump'?
paramNames = FALSE; // check param names during 'diff'?
for ( int current = 1; current < argc ; current++ ) { for ( int current = 1; current < argc ; current++ ) {
// all options have one letter // all options have one letter
@@ -452,12 +497,6 @@ int main(int argc, char **argv)
usage(); usage();
case 'i': case 'i':
if ( mode != Mode_Diff ) {
wxLogError("-i is only valid with diff.");
break;
}
current++; current++;
if ( current >= argc ) { if ( current >= argc ) {
wxLogError("-i option requires an argument."); wxLogError("-i option requires an argument.");
@@ -468,6 +507,26 @@ int main(int argc, char **argv)
ignoreFile = argv[current]; ignoreFile = argv[current];
continue; continue;
case 'p':
if ( mode != Mode_Diff ) {
wxLogError("-p is only valid with diff.");
break;
}
paramNames = TRUE;
continue;
case 'f':
if ( mode != Mode_Dump ) {
wxLogError("-f is only valid with dump.");
break;
}
overwrite = TRUE;
continue;
case 'o': case 'o':
if ( mode != Mode_Dump ) { if ( mode != Mode_Dump ) {
wxLogError("-o is only valid with dump."); wxLogError("-o is only valid with dump.");
@@ -501,12 +560,16 @@ int main(int argc, char **argv)
continue; continue;
default: default:
wxLogError("unknown option '%s'", argv[current]);
break; break;
} }
} }
else {
wxLogError("only one letter options are allowed, not '%s'.",
argv[current]);
}
// only get here after a break from switch or from else branch of if // only get here after a break from switch or from else branch of if
wxLogError("unknown option '%s'", argv[current]);
usage(); usage();
} }
@@ -517,7 +580,7 @@ int main(int argc, char **argv)
else if ( strcmp(argv[current], "dump") == 0 ) else if ( strcmp(argv[current], "dump") == 0 )
mode = Mode_Dump; mode = Mode_Dump;
else { else {
wxLogError("unknown mode '%s'."); wxLogError("unknown mode '%s'.", argv[current]);
usage(); usage();
} }
@@ -538,7 +601,10 @@ int main(int argc, char **argv)
// create a parser object and a visitor derivation // create a parser object and a visitor derivation
CJSourceParser parser; CJSourceParser parser;
HelpGenVisitor visitor(directoryOut); HelpGenVisitor visitor(directoryOut, overwrite);
if ( !!ignoreFile && mode == Mode_Dump )
visitor.GetIgnoreHandler().AddNamesFromFile(ignoreFile);
spContext *ctxTop = NULL; spContext *ctxTop = NULL;
// parse all header files // parse all header files
@@ -555,6 +621,11 @@ int main(int argc, char **argv)
visitor.VisitAll(*ctxTop); visitor.VisitAll(*ctxTop);
visitor.EndVisit(); visitor.EndVisit();
} }
#ifdef __WXDEBUG__
if ( 0 && ctxTop )
ctxTop->Dump("");
#endif // __WXDEBUG__
} }
// parse all TeX files // parse all TeX files
@@ -566,7 +637,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
DocManager docman; DocManager docman(paramNames);
size_t nFiles = filesTeX.GetCount(); size_t nFiles = filesTeX.GetCount();
for ( size_t n = 0; n < nFiles; n++ ) { for ( size_t n = 0; n < nFiles; n++ ) {
@@ -578,7 +649,7 @@ int main(int argc, char **argv)
} }
if ( !!ignoreFile ) if ( !!ignoreFile )
docman.LoadIgnoreFile(ignoreFile); docman.GetIgnoreHandler().AddNamesFromFile(ignoreFile);
docman.DumpDifferences(ctxTop); docman.DumpDifferences(ctxTop);
} }
@@ -590,6 +661,15 @@ int main(int argc, char **argv)
// HelpGenVisitor implementation // HelpGenVisitor implementation
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
HelpGenVisitor::HelpGenVisitor(const wxString& directoryOut,
bool overwrite)
: m_directoryOut(directoryOut)
{
m_overwrite = overwrite;
Reset();
}
void HelpGenVisitor::Reset() void HelpGenVisitor::Reset()
{ {
m_inClass = m_inClass =
@@ -657,20 +737,31 @@ void HelpGenVisitor::EndVisit()
{ {
CloseFunction(); CloseFunction();
m_fileHeader.Empty();
wxLogVerbose("%s: finished generating for the current file.", wxLogVerbose("%s: finished generating for the current file.",
GetCurrentTime("%H:%M:%S")); GetCurrentTime("%H:%M:%S"));
} }
void HelpGenVisitor::VisitFile( spFile& file ) void HelpGenVisitor::VisitFile( spFile& file )
{ {
m_fileHeader = file.mFileName;
wxLogVerbose("%s: started generating docs for classes from file '%s'...", wxLogVerbose("%s: started generating docs for classes from file '%s'...",
GetCurrentTime("%H:%M:%S"), file.mFileName.c_str()); GetCurrentTime("%H:%M:%S"), m_fileHeader.c_str());
} }
void HelpGenVisitor::VisitClass( spClass& cl ) void HelpGenVisitor::VisitClass( spClass& cl )
{ {
m_inClass = FALSE; // will be left FALSE on error
wxString name = cl.GetName(); wxString name = cl.GetName();
if ( m_ignoreNames.IgnoreClass(name) ) {
wxLogVerbose("Skipping ignored class '%s'.", name.c_str());
return;
}
// the file name is built from the class name by removing the leading "wx" // the file name is built from the class name by removing the leading "wx"
// if any and converting it to the lower case // if any and converting it to the lower case
wxString filename = m_directoryOut; wxString filename = m_directoryOut;
@@ -684,12 +775,10 @@ void HelpGenVisitor::VisitClass( spClass& cl )
filename.MakeLower(); filename.MakeLower();
filename += ".tex"; filename += ".tex";
if ( wxFile::Exists(filename) ) { if ( !m_overwrite && wxFile::Exists(filename) ) {
wxLogError("Won't overwrite existing file '%s' - please use '-o'.", wxLogError("Won't overwrite existing file '%s' - please use '-f'.",
filename.c_str()); filename.c_str());
m_inClass = FALSE;
return; return;
} }
@@ -720,7 +809,7 @@ void HelpGenVisitor::VisitClass( spClass& cl )
"\n" "\n"
"\n" "\n"
"\\section{\\class{%s}}\\label{%s}\n", "\\section{\\class{%s}}\\label{%s}\n",
filename.c_str(), GetCurrentTime("%d/%b/%y %H:%M:%S"), m_fileHeader.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';
@@ -931,8 +1020,14 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
{ {
CloseFunction(); CloseFunction();
if ( !m_inClass || !op.IsInClass() ) { if ( !m_inClass ) {
// FIXME that's a bug too // we don't generate docs right now - either we ignore this class
// entirely or we couldn't open the file
return;
}
if ( !op.IsInClass() ) {
// TODO document global functions
wxLogWarning("skipped global function '%s'.", op.GetName().c_str()); wxLogWarning("skipped global function '%s'.", op.GetName().c_str());
return; return;
@@ -943,6 +1038,15 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
return; return;
} }
wxString funcname = op.GetName(),
classname = op.GetClass().GetName();
if ( m_ignoreNames.IgnoreMethod(classname, funcname) ) {
wxLogVerbose("Skipping ignored '%s::%s'.",
classname.c_str(), funcname.c_str());
return;
}
InsertMethodsHeader(); InsertMethodsHeader();
// save state info // save state info
@@ -953,13 +1057,11 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
// start function documentation // start function documentation
wxString totalText; wxString totalText;
const char *funcname = op.GetName().c_str();
const char *classname = op.GetClass().GetName().c_str();
// check for the special case of dtor // check for the special case of dtor
wxString dtor; wxString dtor;
if ( (funcname[0] == '~') && (strcmp(funcname + 1, classname) == 0) ) { if ( (funcname[0] == '~') && (classname == funcname.c_str() + 1) ) {
dtor.Printf("\\destruct{%s}", classname); dtor.Printf("\\destruct{%s}", classname.c_str());
funcname = dtor; funcname = dtor;
} }
@@ -967,12 +1069,12 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
"\\membersection{%s::%s}\\label{%s}\n" "\\membersection{%s::%s}\\label{%s}\n"
"\n" "\n"
"\\%sfunc{%s%s}{%s}{", "\\%sfunc{%s%s}{%s}{",
classname, funcname, classname.c_str(), funcname.c_str(),
MakeLabel(classname, funcname).c_str(), MakeLabel(classname, funcname).c_str(),
op.mIsConstant ? "const" : "", op.mIsConstant ? "const" : "",
op.mIsVirtual ? "virtual " : "", op.mIsVirtual ? "virtual " : "",
op.mRetType.c_str(), op.mRetType.c_str(),
funcname); funcname.c_str());
m_file.WriteTeX(totalText); m_file.WriteTeX(totalText);
} }
@@ -1005,6 +1107,11 @@ void HelpGenVisitor::VisitParameter( spParameter& param )
// DocManager // DocManager
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
DocManager::DocManager(bool checkParamNames)
{
m_checkParamNames = checkParamNames;
}
size_t DocManager::TryMatch(const char *str, const char *match) size_t DocManager::TryMatch(const char *str, const char *match)
{ {
size_t lenMatch = 0; size_t lenMatch = 0;
@@ -1280,7 +1387,7 @@ bool DocManager::ParseTeXFile(const wxString& filename)
lenMatch = TryMatch(current, "void"); lenMatch = TryMatch(current, "void");
if ( !lenMatch ) { if ( !lenMatch ) {
lenMatch = TryMatch(current, "param"); lenMatch = TryMatch(current, "param");
while ( lenMatch ) { while ( lenMatch && (current - buf < len) ) {
current += lenMatch; current += lenMatch;
// now come {paramtype}{paramname} // now come {paramtype}{paramname}
@@ -1423,7 +1530,7 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
const wxString& nameClass = ctxClass->mName; const wxString& nameClass = ctxClass->mName;
int index = m_classes.Index(nameClass); int index = m_classes.Index(nameClass);
if ( index == wxNOT_FOUND ) { if ( index == wxNOT_FOUND ) {
if ( !IgnoreClass(nameClass) ) { if ( !m_ignoreNames.IgnoreClass(nameClass) ) {
foundDiff = TRUE; foundDiff = TRUE;
wxLogError("Class '%s' is not documented at all.", wxLogError("Class '%s' is not documented at all.",
@@ -1466,7 +1573,7 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
} }
if ( aMethodsWithSameName.IsEmpty() && ctxMethod->IsPublic() ) { if ( aMethodsWithSameName.IsEmpty() && ctxMethod->IsPublic() ) {
if ( !IgnoreMethod(nameClass, nameMethod) ) { if ( !m_ignoreNames.IgnoreMethod(nameClass, nameMethod) ) {
foundDiff = TRUE; foundDiff = TRUE;
wxLogError("'%s::%s' is not documented.", wxLogError("'%s::%s' is not documented.",
@@ -1481,7 +1588,7 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
index = (size_t)aMethodsWithSameName[0u]; index = (size_t)aMethodsWithSameName[0u];
methodExists[index] = TRUE; methodExists[index] = TRUE;
if ( IgnoreMethod(nameClass, nameMethod) ) if ( m_ignoreNames.IgnoreMethod(nameClass, nameMethod) )
continue; continue;
if ( !ctxMethod->IsPublic() ) { if ( !ctxMethod->IsPublic() ) {
@@ -1533,7 +1640,8 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
spParameter *ctxParam = (spParameter *)ctx; spParameter *ctxParam = (spParameter *)ctx;
const ParamInfo& param = method.GetParam(nParam); const ParamInfo& param = method.GetParam(nParam);
if ( param.GetName() != ctxParam->mName ) { if ( m_checkParamNames &&
(param.GetName() != ctxParam->mName) ) {
foundDiff = TRUE; foundDiff = TRUE;
wxLogError("Parameter #%d of '%s::%s' should be " wxLogError("Parameter #%d of '%s::%s' should be "
@@ -1575,9 +1683,9 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
} }
} }
else { else {
// TODO add real support for overloaded methods // TODO OVER add real support for overloaded methods
if ( IgnoreMethod(nameClass, nameMethod) ) if ( m_ignoreNames.IgnoreMethod(nameClass, nameMethod) )
continue; continue;
if ( aOverloadedMethods.Index(nameMethod) == wxNOT_FOUND ) { if ( aOverloadedMethods.Index(nameMethod) == wxNOT_FOUND ) {
@@ -1602,7 +1710,7 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
for ( nMethod = 0; nMethod < countMethods; nMethod++ ) { for ( nMethod = 0; nMethod < countMethods; nMethod++ ) {
if ( !methodExists[nMethod] ) { if ( !methodExists[nMethod] ) {
const wxString& nameMethod = methods[nMethod]->GetName(); const wxString& nameMethod = methods[nMethod]->GetName();
if ( !IgnoreMethod(nameClass, nameMethod) ) { if ( !m_ignoreNames.IgnoreMethod(nameClass, nameMethod) ) {
foundDiff = TRUE; foundDiff = TRUE;
wxLogError("'%s::%s' is documented but doesn't exist.", wxLogError("'%s::%s' is documented but doesn't exist.",
@@ -1633,10 +1741,13 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
DocManager::~DocManager() DocManager::~DocManager()
{ {
WX_CLEAR_ARRAY(m_methods); WX_CLEAR_ARRAY(m_methods);
WX_CLEAR_ARRAY(m_ignore);
} }
int DocManager::CompareIgnoreListEntries(IgnoreListEntry *first, // ---------------------------------------------------------------------------
// IgnoreNamesHandler implementation
// ---------------------------------------------------------------------------
int IgnoreNamesHandler::CompareIgnoreListEntries(IgnoreListEntry *first,
IgnoreListEntry *second) IgnoreListEntry *second)
{ {
// first compare the classes // first compare the classes
@@ -1647,7 +1758,7 @@ int DocManager::CompareIgnoreListEntries(IgnoreListEntry *first,
return rc; return rc;
} }
bool DocManager::LoadIgnoreFile(const wxString& filename) bool IgnoreNamesHandler::AddNamesFromFile(const wxString& filename)
{ {
wxFile file(filename, wxFile::read); wxFile file(filename, wxFile::read);
if ( !file.IsOpened() ) if ( !file.IsOpened() )
@@ -1803,11 +1914,52 @@ static const char *GetCurrentTime(const char *timeFormat)
/* /*
$Log$ $Log$
Revision 1.7 1999/02/21 22:32:32 VZ
1. more C++ parser fixes - now it almost parses wx/string.h
a) #if/#ifdef/#else (very) limited support
b) param type fix - now indirection chars are correctly handled
c) class/struct/union distinction
d) public/private fixes
e) Dump() function added - very useful for debugging
2. option to ignore parameter names during 'diff' (in fact, they're ignored
by default, and this option switches it on)
Revision 1.6 1999/02/20 23:00:26 VZ Revision 1.6 1999/02/20 23:00:26 VZ
1. new 'diff' mode which seems to work 1. new 'diff' mode which seems to work
2. output files are not overwritten in 'dmup' mode 2. output files are not overwritten in 'dmup' mode
3. fixes for better handling of const functions and operators 3. fixes for better handling of const functions and operators
----------------------------
revision 1.5
date: 1999/02/15 23:07:25; author: VZ; state: Exp; lines: +106 -45
1. Parser improvements
a) const and virtual methods are parsed correctly (not static yet)
b) "const" which is part of the return type is not swallowed
2. HelpGen improvements: -o outputdir parameter added to the cmd line,
"//---------" kind comments discarded now.
----------------------------
revision 1.4
date: 1999/01/13 14:23:31; author: JS; state: Exp; lines: +4 -4
some tweaks to HelpGen
----------------------------
revision 1.3
date: 1999/01/09 20:18:03; author: JS; state: Exp; lines: +7 -2
HelpGen starting to compile with VC++
----------------------------
revision 1.2
date: 1999/01/08 19:46:22; author: VZ; state: Exp; lines: +208 -35
supports typedefs, generates "See also:" and adds "virtual " for virtual
functions
----------------------------
revision 1.1
date: 1999/01/08 17:45:55; author: VZ; state: Exp;
HelpGen is a prototype of the tool for automatic generation of the .tex files
for wxWindows documentation from C++ headers
*/ */
/* vi: set tw=80 et ts=4 sw=4: */ /* vi: set tw=80 et ts=4 sw=4: */

View File

@@ -1317,16 +1317,55 @@ void CJSourceParser::AddMacroNode( char*& cur )
pPL->mDefType = SP_PREP_DEF_REDEFINE_SYMBOL; pPL->mDefType = SP_PREP_DEF_REDEFINE_SYMBOL;
} }
} }
else else if ( *start == 'i' )
if ( *start == 'i' ) {
if ( cmp_tokens_fast( start, "include", 7 ) ) if ( cmp_tokens_fast( start, "include", 7 ) )
{ {
pPL->mDefType = SP_PREP_DEF_INCLUDE_FILE; pPL->mDefType = SP_PREP_DEF_INCLUDE_FILE;
} }
else if ( *++start == 'f' )
{
// either "#if" or "#ifdef"
cur = start;
skip_token( cur );
get_next_token( cur );
string condition = get_token_str( cur );
// currently, everything except '0' is true
if ( condition == "0" ) {
// skip until the following else or enif
while ( cur < _gSrcEnd ) {
skip_to_eol( cur );
skip_eol( cur );
get_next_token( cur );
if ( *cur++ == '#' && *cur == 'e' )
break;
}
}
// TODO parse the condition...
}
}
else if ( cmp_tokens_fast( start, "else", 4 ) )
{
// skip until "#endif"
while ( cur < _gSrcEnd ) {
skip_to_eol( cur );
skip_eol( cur );
get_next_token( cur );
if ( *cur++ == '#' && cmp_tokens_fast( cur, "endif", 5 ) )
break;
}
}
mpCurCtx->AddMember( pPL ); mpCurCtx->AddMember( pPL );
skip_to_eol( cur );
skip_eol( cur );
restore_line_no( tmpLnNo ); restore_line_no( tmpLnNo );
clear_commets_queue(); clear_commets_queue();
@@ -1537,6 +1576,8 @@ bool CJSourceParser::ParseNameAndRetVal( char*& cur, bool& isAMacro )
pOp->mSrcLineNo = lineNo; pOp->mSrcLineNo = lineNo;
pOp->mSrcOffset = int( start - _gSrcStart ); pOp->mSrcOffset = int( start - _gSrcStart );
pOp->mHeaderLength = int( bracketPos - start ); pOp->mHeaderLength = int( bracketPos - start );
if ( mpCurCtx->GetContextType() == SP_CTX_CLASS )
pOp->mScope = mpCurCtx->mName;
mpCurCtx->AddMember( pOp ); mpCurCtx->AddMember( pOp );
pOp->mVisibility = mCurVis; pOp->mVisibility = mCurVis;
@@ -1552,31 +1593,38 @@ bool CJSourceParser::ParseNameAndRetVal( char*& cur, bool& isAMacro )
// checker whether it's not an operator // checker whether it's not an operator
char chFirst = *pOp->mName.c_str(); char chFirst = *pOp->mName.c_str();
if ( !isalpha(chFirst) && chFirst != '_' && chFirst != '~' ) if ( !isalpha(chFirst) && chFirst != '_' && chFirst != '~' ) {
{
// skip 'operator' // skip 'operator'
skip_next_token_back( cur ); skip_next_token_back( cur );
skip_token_back( cur ); skip_token_back( cur );
string lastToken = get_token_str( cur ); string lastToken = get_token_str( cur );
if ( lastToken == "operator" ) if ( lastToken == "operator" ) {
{
lastToken += pOp->mName; lastToken += pOp->mName;
pOp->mName = lastToken; pOp->mName = lastToken;
} }
else else {
{
// ok, it wasn't an operator after all // ok, it wasn't an operator after all
skip_token( cur ); skip_token( cur );
} }
} }
else if ( pOp->mName == "operator" ) {
skip_token( cur );
get_next_token( cur );
string oper = get_token_str( cur );
pOp->mName += oper;
}
// go backwards to method return type // go backwards to method return type
skip_next_token_back( cur ); skip_next_token_back( cur );
if ( cur >= start ) if ( cur >= start )
{
pOp->mRetType = string( start, size_t( cur-start ) ); string rettype = string( start, size_t( cur-start ) );
rettype.Replace("WXDLLEXPORT ", ""); // FIXME just for now...
pOp->mRetType = rettype;
}
arrange_indirection_tokens_between( pOp->mRetType, pOp->mName ); arrange_indirection_tokens_between( pOp->mRetType, pOp->mName );
@@ -1704,7 +1752,7 @@ bool CJSourceParser::ParseArguments( char*& cur )
pPar->mType = string( blocks[0], len ); pPar->mType = string( blocks[0], len );
arrange_indirection_tokens_between( pPar->mType, pOp->mName ); arrange_indirection_tokens_between( pPar->mType, pPar->mName );
if ( *cur == ')' ) if ( *cur == ')' )
{ {
@@ -1857,17 +1905,21 @@ void CJSourceParser::ParseMemberVar( char*& cur )
} while(1); } while(1);
first = 0;
// set up types for all collected (same-type) attributes; // set up types for all collected (same-type) attributes;
while ( first != members.size() - 1 ) while ( first != members.size() - 1 )
{ {
spAttribute* pAttr = (spAttribute*)members[first]; spAttribute* pAttr = members[first++]->CastToAttribute();
if ( !pAttr )
continue;
if ( !pAttr->mType )
pAttr->mType = type; pAttr->mType = type;
pAttr->mVisibility = mCurVis; pAttr->mVisibility = mCurVis;
if ( !!pAttr->mName )
arrange_indirection_tokens_between( pAttr->mType, pAttr->mName ); arrange_indirection_tokens_between( pAttr->mType, pAttr->mName );
++first;
} }
cur = savedPos; cur = savedPos;
@@ -1975,6 +2027,8 @@ void CJSourceParser::AddClassNode( char*& cur )
{ {
char* ctxStart = cur; char* ctxStart = cur;
string classkeyword = get_token_str( cur );
skip_token( cur ); // skip 'class' keyword skip_token( cur ); // skip 'class' keyword
if ( !get_next_token( cur ) ) return; if ( !get_next_token( cur ) ) return;
@@ -1985,14 +2039,32 @@ void CJSourceParser::AddClassNode( char*& cur )
get_next_token( cur ); get_next_token( cur );
} }
spClass* pClass = new spClass();
mpCurCtx->AddMember( pClass );
// by default all class members are private // by default all class members are private
mCurVis = SP_VIS_PRIVATE; mCurVis = SP_VIS_PRIVATE;
spClass* pClass = new spClass();
if ( classkeyword == "class" )
pClass->mClassSubType = SP_CLTYPE_CLASS;
else if ( classkeyword == "struct" ) {
pClass->mClassSubType = SP_CLTYPE_STRUCTURE;
mCurVis = SP_VIS_PUBLIC;
}
else if ( classkeyword == "union" ) {
pClass->mClassSubType = SP_CLTYPE_UNION;
mCurVis = SP_VIS_PUBLIC;
}
else if ( classkeyword == "interface" )
pClass->mClassSubType = SP_CLTYPE_INTERFACE;
else {
pClass->mClassSubType = SP_CLTYPE_INVALID;
wxFAIL_MSG("unknown class keyword");
}
mpCurCtx->AddMember( pClass );
// attach comments about the class // attach comments about the class
AttachComments( *pClass, cur ); AttachComments( *pClass, cur );

View File

@@ -238,7 +238,7 @@ inline void ScriptTemplate::PrintVar( TVarInfo* pInfo,
if ( !sz ) if ( !sz )
{ {
// DBG:: // DBG::
int u; int u = 0;
++u; ++u;
break; break;
} }

View File

@@ -472,7 +472,7 @@ string spOperation::GetFullName(MarkupTagsT tags)
/***** Implemenentation for class spPreprocessorLine *****/ /***** Implemenentation for class spPreprocessorLine *****/
string spPreprocessorLine::CPP_GetIncludedFileNeme() string spPreprocessorLine::CPP_GetIncludedFileNeme() const
{ {
wxASSERT( GetStatementType() == SP_PREP_DEF_INCLUDE_FILE ); wxASSERT( GetStatementType() == SP_PREP_DEF_INCLUDE_FILE );
@@ -545,3 +545,164 @@ void SourceParserBase::SetPlugin( SourceParserPlugin* pPlugin )
mpPlugin = pPlugin; mpPlugin = pPlugin;
} }
// ===========================================================================
// debug methods
// ===========================================================================
#ifdef __WXDEBUG__
void spContext::Dump(const wxString& indent) const
{
DumpThis(indent);
// increase it for the children
wxString indentChild = indent + " ";
for ( MMemberListT::const_iterator i = mMembers.begin();
i != mMembers.end();
i++ ) {
(*i)->Dump(indentChild);
}
}
void spContext::DumpThis(const wxString& indent) const
{
wxFAIL_MSG("abstract base class can't be found in parser tree!");
}
void spParameter::DumpThis(const wxString& indent) const
{
wxLogDebug("%sparam named '%s' of type '%s'",
indent.c_str(), mName.c_str(), mType.c_str());
}
void spAttribute::DumpThis(const wxString& indent) const
{
wxLogDebug("%svariable named '%s' of type '%s'",
indent.c_str(), mName.c_str(), mType.c_str());
}
void spOperation::DumpThis(const wxString& indent) const
{
wxString protection;
if ( !!mScope ) {
switch ( mVisibility ) {
case SP_VIS_PUBLIC:
protection = "public";
break;
case SP_VIS_PROTECTED:
protection = "protected";
break;
case SP_VIS_PRIVATE:
protection = "private";
break;
default:
wxFAIL_MSG("unknown protection type");
}
}
else {
protection = "global";
}
wxLogDebug("%s%s%s%s function named '%s::%s' of type '%s'",
indent.c_str(),
mIsConstant ? "const " : "",
mIsVirtual ? "virtual " : "",
protection.c_str(),
mScope.c_str(), mName.c_str(), mRetType.c_str());
}
void spPreprocessorLine::DumpThis(const wxString& indent) const
{
wxString kind;
switch ( mDefType ) {
case SP_PREP_DEF_DEFINE_SYMBOL:
kind = "define";
break;
case SP_PREP_DEF_REDEFINE_SYMBOL:
kind = "redefine";
break;
case SP_PREP_DEF_INCLUDE_FILE:
kind.Printf("include (%s)", CPP_GetIncludedFileNeme().c_str());
break;
case SP_PREP_DEF_OTHER:
kind = "other";
break;
}
wxLogDebug("%spreprocessor statement: %s",
indent.c_str(), kind.c_str());
}
void spClass::DumpThis(const wxString& indent) const
{
wxString base;
for ( StrListT::const_iterator i = mSuperClassNames.begin();
i != mSuperClassNames.end();
i++ ) {
if ( !!base )
base += ", ";
base += *i;
}
if ( !base )
base = "none";
wxString kind;
switch ( mClassSubType ) {
case SP_CLTYPE_CLASS:
kind = "class";
break;
case SP_CLTYPE_TEMPLATE_CLASS:
kind = "template class";
break;
case SP_CLTYPE_STRUCTURE:
kind = "struc";
break;
case SP_CLTYPE_UNION:
kind = "union";
break;
case SP_CLTYPE_INTERFACE:
kind = "interface";
break;
default:
wxFAIL_MSG("unknown class subtype");
}
wxLogDebug("%s%s named '%s' (base classes: %s)",
indent.c_str(), kind.c_str(),
mName.c_str(), base.c_str());
}
void spEnumeration::DumpThis(const wxString& indent) const
{
wxLogDebug("%senum named '%s'",
indent.c_str(), mName.c_str());
}
void spTypeDef::DumpThis(const wxString& indent) const
{
wxLogDebug("%stypedef %s = %s",
indent.c_str(), mName.c_str(), mOriginalType.c_str());
}
void spFile::DumpThis(const wxString& indent) const
{
wxLogDebug("%sfile '%s'",
indent.c_str(), mFileName.c_str());
}
#endif // __WXDEBUG__