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

@ -7,7 +7,7 @@
// Created: 22/09/98
// RCS-ID: $Id$
// Copyright: (c) Aleskandars Gluchovas
// Licence: wxWindows licence
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef __CJPARSESR_G__
@ -22,72 +22,72 @@
// class parses given "memory-resident" Java or C++ source code
// and captures information about classes/attrubutes/methods/
// arguments/etc into structures. Conforms with SourceParserBase
// arguments/etc into structures. Conforms with SourceParserBase
// interface requirements.
class CJSourceParser : public SourceParserBase
{
protected:
// begining of the full-text area of the source file
char* mpStart;
// begining of the full-text area of the source file
char* mpStart;
// points to first character after the end
// of teh full-text area
char* mpEnd;
// points to first character after the end
// of teh full-text area
char* mpEnd;
// current "privacy level"
int mCurVis;
// current "privacy level"
int mCurVis;
// current parsing position int full-text area
char* cur;
// current parsing position int full-text area
char* cur;
// about the current class
bool mIsVirtual;
bool mIsTemplate;
size_t mNestingLevel;
// about the current class
bool mIsVirtual;
bool mIsTemplate;
size_t mNestingLevel;
// context data for which is currently being collected
spContext* mpCurCtx;
// context data for which is currently being collected
spContext* mpCurCtx;
int mCurCtxType; // type of the current context
int mCurCtxType; // type of the current context
bool mCommentsOn;
bool mMacrosOn;
bool mCommentsOn;
bool mMacrosOn;
protected:
void AttachComments( spContext& ctx, char* cur );
void ParseKeyword( char*& cur );
bool ParseNameAndRetVal( char*& cur, bool& isAMacro );
bool ParseArguments( char*& cur );
void ParseMemberVar( char*& cur );
void SkipFunction( char*& cur );
void SkipFunctionBody( char*& cur );
bool CheckVisibilty( char*& cur );
void AttachComments( spContext& ctx, char* cur );
void ParseKeyword( char*& cur );
bool ParseNameAndRetVal( char*& cur, bool& isAMacro );
bool ParseArguments( char*& cur );
void ParseMemberVar( char*& cur );
void SkipFunction( char*& cur );
void SkipFunctionBody( char*& cur );
bool CheckVisibilty( char*& cur );
void AddClassNode( char*& cur );
void AddMacroNode( char*& cur );
void AddEnumNode( char*& cur );
void AddTypeDefNode( char*& cur );
void AddClassNode( char*& cur );
void AddMacroNode( char*& cur );
void AddEnumNode( char*& cur );
void AddTypeDefNode( char*& cur );
void DumpOperationInfo( spOperation& info, const string& tab, ostream& os );
void DumpClassHeader( spClass& info, ostream& os );
void DumpClassBody( spClass& info, ostream& os );
void DumpOperationInfo( spOperation& info, const string& tab, ostream& os );
void DumpClassHeader( spClass& info, ostream& os );
void DumpClassBody( spClass& info, ostream& os );
public:
// NOTE:: discarding of macros or comments improves performance and
// decreases memory usage
// NOTE:: discarding of macros or comments improves performance and
// decreases memory usage
CJSourceParser(bool collectCommnets = 1,
bool collectMacros = 1);
CJSourceParser(bool collectCommnets = 1,
bool collectMacros = 1);
// returns the root-node of the created context tree
// (user is responsible for releasing it from the heep)
// "end" should point to the last (character + 1) of the
// source text
// returns the root-node of the created context tree
// (user is responsible for releasing it from the heep)
// "end" should point to the last (character + 1) of the
// source text
virtual spFile* Parse( char* start, char* end );
virtual spFile* Parse( char* start, char* end );
};
// inline'ed helpers used (just info):

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@
(ii) plans for version 2
1. Use wxTextFile for direct file access to avoid one scan method problems
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
1. Merging with existing files
@ -120,15 +121,70 @@ private:
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
class HelpGenVisitor : public spVisitor
{
public:
// ctor
HelpGenVisitor(const wxString& directoryOut) : m_directoryOut(directoryOut)
{
Reset();
}
HelpGenVisitor(const wxString& directoryOut, bool overwrite);
virtual void VisitFile( spFile& fl );
virtual void VisitClass( spClass& cl );
@ -141,6 +197,9 @@ public:
void EndVisit();
// get our `ignore' object
IgnoreNamesHandler& GetIgnoreHandler() { return m_ignoreNames; }
// shut up g++ warning (ain't it stupid?)
virtual ~HelpGenVisitor() { }
@ -160,7 +219,9 @@ protected:
// terminate the function documentation if it was started
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
// state variables
@ -178,6 +239,10 @@ protected:
// headers included by this file
wxArrayString m_headers;
// ignore handler: tells us which classes to ignore for doc generation
// purposes
IgnoreNamesHandler m_ignoreNames;
private:
HelpGenVisitor(const HelpGenVisitor&);
HelpGenVisitor& operator=(const HelpGenVisitor&);
@ -189,18 +254,18 @@ private:
class DocManager
{
public:
DocManager() : m_ignore(CompareIgnoreListEntries) { }
DocManager(bool checkParamNames);
~DocManager();
// load file with class names and function names to ignore during diff
bool LoadIgnoreFile(const wxString& filename);
// returns FALSE on failure
bool ParseTeXFile(const wxString& filename);
// returns FALSE if there were any differences
bool DumpDifferences(spContext *ctxTop) const;
// get our `ignore' object
IgnoreNamesHandler& GetIgnoreHandler() { return m_ignoreNames; }
protected:
// parsing TeX files
// -----------------
@ -242,40 +307,8 @@ protected:
// 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;
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, "");
}
IgnoreNamesHandler m_ignoreNames;
// information about all functions documented in the TeX file(s)
// -------------------------------------------------------------
@ -367,6 +400,13 @@ protected:
// the class name appears in m_classes
wxArrayString m_classes;
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"
" -H give this usage message\n"
" -V print the version info\n"
" -i file file with classes/function to ignore\n"
"\n"
" where mode is one of: dump, diff\n"
"\n"
" dump means generate .tex files for TeX2RTF converter from specified\n"
" headers files, mode options are:\n"
" -f overwrite existing files\n"
" -o outdir directory for generated files\n"
"\n"
" diff means compare the set of methods documented .tex file with the\n"
" methods declared in the header:\n"
" %s diff <file.h> <files.tex...>.\n"
" options are:\n"
" -i file file with classes/function to ignore during diff\n"
" mode specific options are:\n"
" -p do check parameter names (not done by default)\n"
"\n", basename.c_str(), basename.c_str());
exit(1);
@ -430,7 +472,10 @@ int main(int argc, char **argv)
}
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++ ) {
// all options have one letter
@ -452,12 +497,6 @@ int main(int argc, char **argv)
usage();
case 'i':
if ( mode != Mode_Diff ) {
wxLogError("-i is only valid with diff.");
break;
}
current++;
if ( current >= argc ) {
wxLogError("-i option requires an argument.");
@ -468,6 +507,26 @@ int main(int argc, char **argv)
ignoreFile = argv[current];
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':
if ( mode != Mode_Dump ) {
wxLogError("-o is only valid with dump.");
@ -501,12 +560,16 @@ int main(int argc, char **argv)
continue;
default:
wxLogError("unknown option '%s'", argv[current]);
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
wxLogError("unknown option '%s'", argv[current]);
usage();
}
@ -517,7 +580,7 @@ int main(int argc, char **argv)
else if ( strcmp(argv[current], "dump") == 0 )
mode = Mode_Dump;
else {
wxLogError("unknown mode '%s'.");
wxLogError("unknown mode '%s'.", argv[current]);
usage();
}
@ -538,7 +601,10 @@ int main(int argc, char **argv)
// create a parser object and a visitor derivation
CJSourceParser parser;
HelpGenVisitor visitor(directoryOut);
HelpGenVisitor visitor(directoryOut, overwrite);
if ( !!ignoreFile && mode == Mode_Dump )
visitor.GetIgnoreHandler().AddNamesFromFile(ignoreFile);
spContext *ctxTop = NULL;
// parse all header files
@ -555,6 +621,11 @@ int main(int argc, char **argv)
visitor.VisitAll(*ctxTop);
visitor.EndVisit();
}
#ifdef __WXDEBUG__
if ( 0 && ctxTop )
ctxTop->Dump("");
#endif // __WXDEBUG__
}
// parse all TeX files
@ -566,7 +637,7 @@ int main(int argc, char **argv)
return 1;
}
DocManager docman;
DocManager docman(paramNames);
size_t nFiles = filesTeX.GetCount();
for ( size_t n = 0; n < nFiles; n++ ) {
@ -578,7 +649,7 @@ int main(int argc, char **argv)
}
if ( !!ignoreFile )
docman.LoadIgnoreFile(ignoreFile);
docman.GetIgnoreHandler().AddNamesFromFile(ignoreFile);
docman.DumpDifferences(ctxTop);
}
@ -590,6 +661,15 @@ int main(int argc, char **argv)
// HelpGenVisitor implementation
// -----------------------------------------------------------------------------
HelpGenVisitor::HelpGenVisitor(const wxString& directoryOut,
bool overwrite)
: m_directoryOut(directoryOut)
{
m_overwrite = overwrite;
Reset();
}
void HelpGenVisitor::Reset()
{
m_inClass =
@ -657,20 +737,31 @@ void HelpGenVisitor::EndVisit()
{
CloseFunction();
m_fileHeader.Empty();
wxLogVerbose("%s: finished generating for the current file.",
GetCurrentTime("%H:%M:%S"));
}
void HelpGenVisitor::VisitFile( spFile& file )
{
m_fileHeader = file.mFileName;
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 )
{
m_inClass = FALSE; // will be left FALSE on error
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"
// if any and converting it to the lower case
wxString filename = m_directoryOut;
@ -684,12 +775,10 @@ void HelpGenVisitor::VisitClass( spClass& cl )
filename.MakeLower();
filename += ".tex";
if ( wxFile::Exists(filename) ) {
wxLogError("Won't overwrite existing file '%s' - please use '-o'.",
if ( !m_overwrite && wxFile::Exists(filename) ) {
wxLogError("Won't overwrite existing file '%s' - please use '-f'.",
filename.c_str());
m_inClass = FALSE;
return;
}
@ -720,7 +809,7 @@ void HelpGenVisitor::VisitClass( spClass& cl )
"\n"
"\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());
totalText << header << '\n';
@ -931,8 +1020,14 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
{
CloseFunction();
if ( !m_inClass || !op.IsInClass() ) {
// FIXME that's a bug too
if ( !m_inClass ) {
// 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());
return;
@ -943,6 +1038,15 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
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();
// save state info
@ -953,13 +1057,11 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
// start function documentation
wxString totalText;
const char *funcname = op.GetName().c_str();
const char *classname = op.GetClass().GetName().c_str();
// check for the special case of dtor
wxString dtor;
if ( (funcname[0] == '~') && (strcmp(funcname + 1, classname) == 0) ) {
dtor.Printf("\\destruct{%s}", classname);
if ( (funcname[0] == '~') && (classname == funcname.c_str() + 1) ) {
dtor.Printf("\\destruct{%s}", classname.c_str());
funcname = dtor;
}
@ -967,12 +1069,12 @@ void HelpGenVisitor::VisitOperation( spOperation& op )
"\\membersection{%s::%s}\\label{%s}\n"
"\n"
"\\%sfunc{%s%s}{%s}{",
classname, funcname,
classname.c_str(), funcname.c_str(),
MakeLabel(classname, funcname).c_str(),
op.mIsConstant ? "const" : "",
op.mIsVirtual ? "virtual " : "",
op.mRetType.c_str(),
funcname);
funcname.c_str());
m_file.WriteTeX(totalText);
}
@ -1005,6 +1107,11 @@ void HelpGenVisitor::VisitParameter( spParameter& param )
// DocManager
// ---------------------------------------------------------------------------
DocManager::DocManager(bool checkParamNames)
{
m_checkParamNames = checkParamNames;
}
size_t DocManager::TryMatch(const char *str, const char *match)
{
size_t lenMatch = 0;
@ -1280,7 +1387,7 @@ bool DocManager::ParseTeXFile(const wxString& filename)
lenMatch = TryMatch(current, "void");
if ( !lenMatch ) {
lenMatch = TryMatch(current, "param");
while ( lenMatch ) {
while ( lenMatch && (current - buf < len) ) {
current += lenMatch;
// now come {paramtype}{paramname}
@ -1423,7 +1530,7 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
const wxString& nameClass = ctxClass->mName;
int index = m_classes.Index(nameClass);
if ( index == wxNOT_FOUND ) {
if ( !IgnoreClass(nameClass) ) {
if ( !m_ignoreNames.IgnoreClass(nameClass) ) {
foundDiff = TRUE;
wxLogError("Class '%s' is not documented at all.",
@ -1466,7 +1573,7 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
}
if ( aMethodsWithSameName.IsEmpty() && ctxMethod->IsPublic() ) {
if ( !IgnoreMethod(nameClass, nameMethod) ) {
if ( !m_ignoreNames.IgnoreMethod(nameClass, nameMethod) ) {
foundDiff = TRUE;
wxLogError("'%s::%s' is not documented.",
@ -1481,7 +1588,7 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
index = (size_t)aMethodsWithSameName[0u];
methodExists[index] = TRUE;
if ( IgnoreMethod(nameClass, nameMethod) )
if ( m_ignoreNames.IgnoreMethod(nameClass, nameMethod) )
continue;
if ( !ctxMethod->IsPublic() ) {
@ -1533,7 +1640,8 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
spParameter *ctxParam = (spParameter *)ctx;
const ParamInfo& param = method.GetParam(nParam);
if ( param.GetName() != ctxParam->mName ) {
if ( m_checkParamNames &&
(param.GetName() != ctxParam->mName) ) {
foundDiff = TRUE;
wxLogError("Parameter #%d of '%s::%s' should be "
@ -1575,9 +1683,9 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
}
}
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;
if ( aOverloadedMethods.Index(nameMethod) == wxNOT_FOUND ) {
@ -1602,7 +1710,7 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
for ( nMethod = 0; nMethod < countMethods; nMethod++ ) {
if ( !methodExists[nMethod] ) {
const wxString& nameMethod = methods[nMethod]->GetName();
if ( !IgnoreMethod(nameClass, nameMethod) ) {
if ( !m_ignoreNames.IgnoreMethod(nameClass, nameMethod) ) {
foundDiff = TRUE;
wxLogError("'%s::%s' is documented but doesn't exist.",
@ -1633,11 +1741,14 @@ bool DocManager::DumpDifferences(spContext *ctxTop) const
DocManager::~DocManager()
{
WX_CLEAR_ARRAY(m_methods);
WX_CLEAR_ARRAY(m_ignore);
}
int DocManager::CompareIgnoreListEntries(IgnoreListEntry *first,
IgnoreListEntry *second)
// ---------------------------------------------------------------------------
// IgnoreNamesHandler implementation
// ---------------------------------------------------------------------------
int IgnoreNamesHandler::CompareIgnoreListEntries(IgnoreListEntry *first,
IgnoreListEntry *second)
{
// first compare the classes
int rc = first->m_classname.Cmp(second->m_classname);
@ -1647,7 +1758,7 @@ int DocManager::CompareIgnoreListEntries(IgnoreListEntry *first,
return rc;
}
bool DocManager::LoadIgnoreFile(const wxString& filename)
bool IgnoreNamesHandler::AddNamesFromFile(const wxString& filename)
{
wxFile file(filename, wxFile::read);
if ( !file.IsOpened() )
@ -1803,11 +1914,52 @@ static const char *GetCurrentTime(const char *timeFormat)
/*
$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
1. new 'diff' mode which seems to work
2. output files are not overwritten in 'dmup' mode
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: */

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -6,7 +6,7 @@
// Created: 22/09/98
// RCS-ID: $Id$
// Copyright: (c) Aleskandars Gluchovas
// Licence: wxWindows licence
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
@ -33,387 +33,387 @@
/***** Implementation for class spVisitor *****/
void spVisitor::VisitAll( spContext& atContext,
bool sortContent
)
bool sortContent
)
{
mSiblingSkipped = FALSE;
mChildSkipped = FALSE;
mContextMask = SP_CTX_ANY; // FIXME:: should be an arg.
mSiblingSkipped = FALSE;
mChildSkipped = FALSE;
mContextMask = SP_CTX_ANY; // FIXME:: should be an arg.
if ( sortContent && !atContext.IsSorted() )
if ( sortContent && !atContext.IsSorted() )
atContext.SortMembers();
atContext.SortMembers();
mpCurCxt = &atContext; // FIXME:: this is dirty, restoring it each time
mpCurCxt = &atContext; // FIXME:: this is dirty, restoring it each time
if ( atContext.GetContextType() & mContextMask )
if ( atContext.GetContextType() & mContextMask )
atContext.AcceptVisitor( *this );
atContext.AcceptVisitor( *this );
MMemberListT& members = atContext.GetMembers();
MMemberListT& members = atContext.GetMembers();
for( size_t i = 0; i != members.size(); ++i )
{
if ( mSiblingSkipped )
return;
for( size_t i = 0; i != members.size(); ++i )
{
if ( mSiblingSkipped )
return;
if ( !mChildSkipped )
{
size_t prevSz = members.size();
if ( !mChildSkipped )
{
size_t prevSz = members.size();
// visit members of the context recursivelly
VisitAll( *members[i], sortContent );
// visit members of the context recursivelly
VisitAll( *members[i], sortContent );
if ( members.size() != prevSz )
if ( members.size() != prevSz )
--i; // current member was removed!
--i; // current member was removed!
mChildSkipped = 0;
}
}
mChildSkipped = 0;
}
}
}
void spVisitor::RemoveCurrentContext()
{
if ( mpCurCxt->GetParent() )
if ( mpCurCxt->GetParent() )
mpCurCxt->GetParent()->RemoveChild( mpCurCxt );
mpCurCxt->GetParent()->RemoveChild( mpCurCxt );
}
void spVisitor::SkipSiblings()
{
mSiblingSkipped = TRUE;
mSiblingSkipped = TRUE;
}
void spVisitor::SkipChildren()
{
mChildSkipped = TRUE;
mChildSkipped = TRUE;
}
void spVisitor::SetFilter( int contextMask )
{
mContextMask = contextMask;
mContextMask = contextMask;
}
/***** Implementation for class spComment *****/
bool spComment::IsMultiline() const
{
return mIsMultiline;
return mIsMultiline;
}
bool spComment::StartsParagraph() const
{
return mStartsPar;
return mStartsPar;
}
string& spComment::GetText()
{
return mText;
return mText;
}
string spComment::GetText() const
{
return mText;
return mText;
}
/***** Implementation for class spContext *****/
spContext::spContext()
: mpParent ( NULL ),
mpFirstOccurence( NULL ),
mAlreadySorted ( FALSE ),
: mpParent ( NULL ),
mpFirstOccurence( NULL ),
mAlreadySorted ( FALSE ),
mSrcLineNo (-1),
mSrcOffset (-1),
mContextLength(-1),
mLastScrLineNo(-1),
mSrcLineNo (-1),
mSrcOffset (-1),
mContextLength(-1),
mLastScrLineNo(-1),
mHeaderLength (-1),
mFooterLength (-1),
mHeaderLength (-1),
mFooterLength (-1),
mFirstCharPos (-1),
mLastCharPos (-1),
mFirstCharPos (-1),
mLastCharPos (-1),
mVisibility( SP_VIS_PRIVATE ),
mVisibility( SP_VIS_PRIVATE ),
mIsVirtualContext ( FALSE ),
mVirtualContextHasChildren( FALSE ),
mIsVirtualContext ( FALSE ),
mVirtualContextHasChildren( FALSE ),
mpUserData( NULL )
mpUserData( NULL )
{}
void spContext::RemoveChildren()
{
for( size_t i = 0; i != mMembers.size(); ++i )
delete mMembers[i];
for( size_t i = 0; i != mMembers.size(); ++i )
delete mMembers[i];
mMembers.erase( mMembers.begin(), mMembers.end() );
mMembers.erase( mMembers.begin(), mMembers.end() );
}
spContext::~spContext()
{
RemoveChildren();
RemoveChildren();
for( size_t i = 0; i != mComments.size(); ++i )
delete mComments[i];
for( size_t i = 0; i != mComments.size(); ++i )
delete mComments[i];
}
bool spContext::IsSorted()
{
return mAlreadySorted;
return mAlreadySorted;
}
void spContext::GetContextList( MMemberListT& lst, int contextMask )
{
for( size_t i = 0; i != mMembers.size(); ++i )
{
spContext& member = *mMembers[i];
for( size_t i = 0; i != mMembers.size(); ++i )
{
spContext& member = *mMembers[i];
if ( member.GetContextType() & contextMask )
if ( member.GetContextType() & contextMask )
lst.push_back( &member );
lst.push_back( &member );
// collect required contexts recursively
member.GetContextList( lst, contextMask );
}
// collect required contexts recursively
member.GetContextList( lst, contextMask );
}
}
bool spContext::HasComments()
{
return ( mComments.size() != 0 );
return ( mComments.size() != 0 );
}
void spContext::RemoveChild( spContext* pChild )
{
for( size_t i = 0; i != mMembers.size(); ++i )
for( size_t i = 0; i != mMembers.size(); ++i )
if ( mMembers[i] == pChild )
{
mMembers.erase( &mMembers[i] );
if ( mMembers[i] == pChild )
{
mMembers.erase( &mMembers[i] );
delete pChild;
return;
}
delete pChild;
return;
}
// the given child should exist on the parent's list
wxASSERT( 0 );
// the given child should exist on the parent's list
wxASSERT( 0 );
}
spContext* spContext::GetEnclosingContext( int mask )
{
spContext* cur = this->GetParent();
spContext* cur = this->GetParent();
while ( cur && !(cur->GetContextType() & mask) )
cur = cur->GetParent();
while ( cur && !(cur->GetContextType() & mask) )
cur = cur->GetParent();
return cur;
return cur;
}
bool spContext::PositionIsKnown()
{
return ( mSrcOffset != (-1) && mContextLength != (-1) );
return ( mSrcOffset != (-1) && mContextLength != (-1) );
}
bool spContext::IsVirtualContext()
{
return mIsVirtualContext;
return mIsVirtualContext;
}
bool spContext::VitualContextHasChildren()
{
return mVirtualContextHasChildren;
return mVirtualContextHasChildren;
}
string spContext::GetVirtualContextBody()
{
wxASSERT( mIsVirtualContext );
wxASSERT( mIsVirtualContext );
return mVirtualContextBody;
return mVirtualContextBody;
}
string spContext::GetFooterOfVirtualContextBody()
{
wxASSERT( mIsVirtualContext );
wxASSERT( mIsVirtualContext );
return mVittualContextFooter;
return mVittualContextFooter;
}
void spContext::SetVirtualContextBody( const string& body,
bool hasChildren,
const string& footer )
bool hasChildren,
const string& footer )
{
mVirtualContextHasChildren = hasChildren;
mVirtualContextHasChildren = hasChildren;
mVirtualContextBody = body;
mVittualContextFooter = footer;
mVirtualContextBody = body;
mVittualContextFooter = footer;
// atuomaticllay becomes virtual context
// atuomaticllay becomes virtual context
mIsVirtualContext = TRUE;
mIsVirtualContext = TRUE;
}
string spContext::GetBody( spContext* pCtx )
{
if ( ( pCtx == NULL || pCtx == this ) && mIsVirtualContext )
return mVirtualContextBody;
if ( ( pCtx == NULL || pCtx == this ) && mIsVirtualContext )
return mVirtualContextBody;
if ( GetParent() )
if ( GetParent() )
return GetParent()->GetBody( ( pCtx != NULL ) ? pCtx : this );
else
return ""; // source-fragment cannot be found
return GetParent()->GetBody( ( pCtx != NULL ) ? pCtx : this );
else
return ""; // source-fragment cannot be found
}
string spContext::GetHeader( spContext* pCtx )
{
if ( GetParent() )
if ( GetParent() )
return GetParent()->GetHeader( ( pCtx != NULL ) ? pCtx : this );
else
return ""; // source-fragment cannot be found
return GetParent()->GetHeader( ( pCtx != NULL ) ? pCtx : this );
else
return ""; // source-fragment cannot be found
}
bool spContext::IsFirstOccurence()
{
return ( mpFirstOccurence != 0 );
return ( mpFirstOccurence != 0 );
}
spContext* spContext::GetFirstOccurence()
{
// this object should not itself be
// the first occurence of the context
wxASSERT( mpFirstOccurence != 0 );
// this object should not itself be
// the first occurence of the context
wxASSERT( mpFirstOccurence != 0 );
return mpFirstOccurence;
return mpFirstOccurence;
}
void spContext::AddMember( spContext* pMember )
{
mMembers.push_back( pMember );
mMembers.push_back( pMember );
pMember->mpParent = this;
pMember->mpParent = this;
}
void spContext::AddComment( spComment* pComment )
{
mComments.push_back( pComment );
mComments.push_back( pComment );
}
MMemberListT& spContext::GetMembers()
{
return mMembers;
return mMembers;
}
spContext* spContext::FindContext( const string& identifier,
int contextType,
bool searchSubMembers
)
int contextType,
bool searchSubMembers
)
{
for( size_t i = 0; i != mMembers.size(); ++i )
{
spContext& member = *mMembers[i];
for( size_t i = 0; i != mMembers.size(); ++i )
{
spContext& member = *mMembers[i];
if ( member.GetName() == identifier &&
( contextType & member.GetContextType() )
)
if ( member.GetName() == identifier &&
( contextType & member.GetContextType() )
)
return &member;
return &member;
if ( searchSubMembers )
{
spContext* result =
member.FindContext( identifier, contextType, 1 );
if ( searchSubMembers )
{
spContext* result =
member.FindContext( identifier, contextType, 1 );
if ( result ) return result;
}
}
if ( result ) return result;
}
}
return 0;
return 0;
}
void spContext::RemoveThisContext()
{
if ( mpParent )
mpParent->RemoveChild( this );
else
// context should have a parent
wxASSERT(0);
if ( mpParent )
mpParent->RemoveChild( this );
else
// context should have a parent
wxASSERT(0);
}
spContext* spContext::GetOutterContext()
{
return mpParent;
return mpParent;
}
bool spContext::HasOutterContext()
{
return ( mpParent != 0 );
return ( mpParent != 0 );
}
bool spContext::IsInFile()
{
return ( GetOutterContext()->GetContextType() == SP_CTX_FILE );
return ( GetOutterContext()->GetContextType() == SP_CTX_FILE );
}
bool spContext::IsInNameSpace()
{
return ( GetOutterContext()->GetContextType() == SP_CTX_NAMESPACE );
return ( GetOutterContext()->GetContextType() == SP_CTX_NAMESPACE );
}
bool spContext::IsInClass()
{
return ( GetOutterContext()->GetContextType() == SP_CTX_CLASS );
return ( GetOutterContext()->GetContextType() == SP_CTX_CLASS );
}
bool spContext::IsInOperation()
{
return ( GetOutterContext()->GetContextType() == SP_CTX_OPERATION );
return ( GetOutterContext()->GetContextType() == SP_CTX_OPERATION );
}
spClass& spContext::GetClass()
{
wxASSERT( GetOutterContext()->GetType() == SP_CTX_CLASS );
return *((spClass*)mpParent );
wxASSERT( GetOutterContext()->GetType() == SP_CTX_CLASS );
return *((spClass*)mpParent );
}
spFile& spContext::GetFile()
{
wxASSERT( GetOutterContext()->GetType() == SP_CTX_FILE );
return *((spFile*)mpParent );
wxASSERT( GetOutterContext()->GetType() == SP_CTX_FILE );
return *((spFile*)mpParent );
}
spNameSpace& spContext::GetNameSpace()
{
wxASSERT( GetOutterContext()->GetType() == SP_CTX_NAMESPACE );
return *((spNameSpace*)mpParent );
wxASSERT( GetOutterContext()->GetType() == SP_CTX_NAMESPACE );
return *((spNameSpace*)mpParent );
}
spOperation& spContext::GetOperation()
{
wxASSERT( GetOutterContext()->GetType() == SP_CTX_OPERATION );
return *((spOperation*)mpParent );
wxASSERT( GetOutterContext()->GetType() == SP_CTX_OPERATION );
return *((spOperation*)mpParent );
}
/***** Implementation for class spClass *****/
void spClass::SortMembers()
{
// TBD::
// TBD::
}
/***** Implementation for class spOperation *****/
spOperation::spOperation()
: mHasDefinition( FALSE )
: mHasDefinition( FALSE )
{
mIsConstant =
mIsVirtual =
@ -422,83 +422,83 @@ spOperation::spOperation()
string spOperation::GetFullName(MarkupTagsT tags)
{
string txt = tags[TAG_BOLD].start + mRetType;
txt += " ";
txt += mName;
txt += "( ";
txt += tags[TAG_BOLD].end;
for( size_t i = 0; i != mMembers.size(); ++i )
{
// DBG::
wxASSERT( mMembers[i]->GetContextType() == SP_CTX_PARAMETER );
string txt = tags[TAG_BOLD].start + mRetType;
txt += " ";
txt += mName;
txt += "( ";
txt += tags[TAG_BOLD].end;
for( size_t i = 0; i != mMembers.size(); ++i )
{
// DBG::
wxASSERT( mMembers[i]->GetContextType() == SP_CTX_PARAMETER );
spParameter& param = *((spParameter*)mMembers[i]);
spParameter& param = *((spParameter*)mMembers[i]);
if ( i != 0 )
txt += ", ";
txt += tags[TAG_BOLD].start;
txt += param.mType;
if ( i != 0 )
txt += ", ";
txt += tags[TAG_BOLD].start;
txt += param.mType;
txt += tags[TAG_BOLD].end;
txt += tags[TAG_ITALIC].start;
txt += tags[TAG_BOLD].end;
txt += tags[TAG_ITALIC].start;
txt += " ";
txt += param.mName;
txt += " ";
txt += param.mName;
if ( param.mInitVal != "" )
{
txt += " = ";
txt += tags[TAG_BOLD].start;
if ( param.mInitVal != "" )
{
txt += " = ";
txt += tags[TAG_BOLD].start;
txt += param.mInitVal;
txt += param.mInitVal;
txt += tags[TAG_BOLD].end;
}
txt += tags[TAG_BOLD].end;
}
txt += tags[TAG_ITALIC].end;;
}
txt += tags[TAG_ITALIC].end;;
}
txt += tags[TAG_BOLD].start;
txt += " )";
txt += tags[TAG_BOLD].end;
txt += tags[TAG_BOLD].start;
txt += " )";
txt += tags[TAG_BOLD].end;
// TBD:: constantness of method
// TBD:: constantness of method
return txt;
return txt;
}
/***** 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 );
size_t i = 0;
size_t i = 0;
while( i < mLine.length() && mLine[i] != '"' && mLine[i] != '<' )
++i;
while( i < mLine.length() && mLine[i] != '"' && mLine[i] != '<' )
++i;
++i;
++i;
size_t start = i;
size_t start = i;
while( i < mLine.length() && mLine[i] != '"' && mLine[i] != '>' )
while( i < mLine.length() && mLine[i] != '"' && mLine[i] != '>' )
++i;
++i;
if ( start < mLine.length() )
{
string fname;
fname.append( mLine, start, ( i - start ) );
if ( start < mLine.length() )
{
string fname;
fname.append( mLine, start, ( i - start ) );
return fname;
}
else
return ""; // syntax error probably
return fname;
}
else
return ""; // syntax error probably
}
@ -507,41 +507,202 @@ string spPreprocessorLine::CPP_GetIncludedFileNeme()
SourceParserBase::SourceParserBase()
: mpFileBuf( NULL ),
mFileBufSz( 0 ),
: mpFileBuf( NULL ),
mFileBufSz( 0 ),
mpPlugin( NULL )
mpPlugin( NULL )
{}
SourceParserBase::~SourceParserBase()
{
if ( mpFileBuf ) free( mpFileBuf );
if ( mpFileBuf ) free( mpFileBuf );
if ( mpPlugin ) delete mpPlugin;
if ( mpPlugin ) delete mpPlugin;
}
spFile* SourceParserBase::ParseFile( const char* fname )
{
// FIXME:: the below should not be fixed!
// FIXME:: the below should not be fixed!
const size_t MAX_BUF_SIZE = 1024*256;
const size_t MAX_BUF_SIZE = 1024*256;
if ( !mpFileBuf ) mpFileBuf = (char*)malloc( MAX_BUF_SIZE );
if ( !mpFileBuf ) mpFileBuf = (char*)malloc( MAX_BUF_SIZE );
mFileBufSz = MAX_BUF_SIZE;
mFileBufSz = MAX_BUF_SIZE;
FILE* fp = fopen( fname, "rt" );
FILE* fp = fopen( fname, "rt" );
if ( (int)fp == -1 || !fp ) return NULL;
if ( (int)fp == -1 || !fp ) return NULL;
int sz = fread( mpFileBuf, 1, mFileBufSz, fp );
int sz = fread( mpFileBuf, 1, mFileBufSz, fp );
return Parse( mpFileBuf, mpFileBuf + sz );
return Parse( mpFileBuf, mpFileBuf + sz );
}
void SourceParserBase::SetPlugin( SourceParserPlugin* pPlugin )
{
if ( mpPlugin ) delete mpPlugin;
if ( mpPlugin ) delete mpPlugin;
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__