HelpGen is a prototype of the tool for automatic generation of the .tex files
for wxWindows documentation from C++ headers git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1347 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
568
utils/HelpGen/src/docripper.cpp
Normal file
568
utils/HelpGen/src/docripper.cpp
Normal file
@@ -0,0 +1,568 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: No names yet.
|
||||
// Purpose: Contrib. demo
|
||||
// Author: Aleksandras Gluchovas
|
||||
// Modified by:
|
||||
// Created: 22/09/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Aleskandars Gluchovas
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "docripper.h"
|
||||
|
||||
#include <iostream.h>
|
||||
|
||||
// script templates
|
||||
|
||||
// ***** currently only HTML versions of variouse templates available ***** //
|
||||
|
||||
static const char* HTM_TopTempl =
|
||||
|
||||
"<html><body bgcolor=#FFFFFF>\n\
|
||||
\n\n<!------ Automatically Generated by \"wxDocRipper\"------->\n\n\n\
|
||||
<p><h2>$(NAME)</h2><p>\n\
|
||||
<ul>\n\
|
||||
$(REFLIST)\
|
||||
</ul><p>\n\n\
|
||||
";
|
||||
|
||||
static const char* HTM_ContentIdxTempl =
|
||||
|
||||
"\
|
||||
<a name=\"r$(ID)_$(NAME)\">\n\
|
||||
<p><hr>\n\
|
||||
<h2><p>$(NAME)<p></h2>\
|
||||
<ul>\n\
|
||||
$(REFLIST)\
|
||||
</ul><p>\n\n\
|
||||
";
|
||||
|
||||
static const char* HTM_SuperContentTempl =
|
||||
|
||||
"\
|
||||
<a name=\"r$(ID)_$(NAME)\">\n\
|
||||
<p><hr>\n\
|
||||
<p><h2>$(NAME)<p></h2>\
|
||||
$(BODY)\n\
|
||||
";
|
||||
|
||||
static const char* HTM_SubContentTempl =
|
||||
|
||||
"\
|
||||
<a name=\"r$(ID)_$(NAME)\">\n\
|
||||
<p><hr>\n\
|
||||
<p><h3>$(NAME)<p></h3>\
|
||||
$(BODY)\n\
|
||||
";
|
||||
|
||||
static const char* HTM_OutLineTempl =
|
||||
|
||||
"\
|
||||
<p>\n\
|
||||
<b><font color=\"#FF0000\">$(NAME)</font></b><p>\n\
|
||||
";
|
||||
|
||||
static const char* HTM_OutLine1Templ =
|
||||
|
||||
"\
|
||||
<p>\n\
|
||||
<b><i><font color=\"#101010\">$(NAME)</font></i></b>\n\
|
||||
<ul>\n\
|
||||
$(REFLIST)\
|
||||
</ul>\n\n\
|
||||
";
|
||||
|
||||
static const char* HTM_RefTempl =
|
||||
|
||||
"\
|
||||
<li><a href=\"#r$(ID)_$(NAME)\">$(NAME)</A>\n\
|
||||
";
|
||||
|
||||
static const char* HTM_DeadRefTempl =
|
||||
|
||||
"\
|
||||
<li></b>$(NAME)\n\
|
||||
";
|
||||
|
||||
/***** Implementation for class RipperDocGen *****/
|
||||
|
||||
RipperDocGen::RipperDocGen()
|
||||
|
||||
: mTopTempl ( HTM_TopTempl ),
|
||||
mContentIdxTempl ( HTM_ContentIdxTempl ),
|
||||
mSuperContentTempl( HTM_SuperContentTempl ),
|
||||
mSubContentTempl ( HTM_SubContentTempl ),
|
||||
mOutLineTempl ( HTM_OutLineTempl ),
|
||||
mOutLine1Templ ( HTM_OutLine1Templ ),
|
||||
|
||||
mRefTempl ( HTM_RefTempl ),
|
||||
mDeadRefTempl ( HTM_DeadRefTempl ),
|
||||
|
||||
mpCurClassSect(0)
|
||||
{ // topIndex is not referenced
|
||||
mpTopIdx = new ScriptSection( "Source Code Contents" , "", &mTopTempl , 0 );
|
||||
mpClassIdx = new ScriptSection( "Classes Reference" , "", &mContentIdxTempl, &mRefTempl );
|
||||
mpEnumIdx = new ScriptSection( "Enumerations Reference" , "", &mContentIdxTempl, &mRefTempl );
|
||||
mpTypeDefIdx = new ScriptSection( "Type Definitions Reference" , "", &mContentIdxTempl, &mRefTempl );
|
||||
mpMacroIdx = new ScriptSection( "Macros Reference" , "", &mContentIdxTempl, &mRefTempl );
|
||||
mpGlobalVarsIdx = new ScriptSection( "Global Variables Reference" , "", &mContentIdxTempl, &mRefTempl );
|
||||
mpGlobalFuncIdx = new ScriptSection( "Global Functions Reference", "", &mContentIdxTempl, &mRefTempl );
|
||||
mpConstIdx = new ScriptSection( "Constants Reference" , "", &mContentIdxTempl, &mRefTempl );
|
||||
|
||||
// assemble top index
|
||||
mpTopIdx->AddSection( mpClassIdx , 1 );
|
||||
mpTopIdx->AddSection( mpEnumIdx , 1 );
|
||||
mpTopIdx->AddSection( mpTypeDefIdx , 1 );
|
||||
mpTopIdx->AddSection( mpMacroIdx , 1 );
|
||||
mpTopIdx->AddSection( mpGlobalVarsIdx, 1 );
|
||||
mpTopIdx->AddSection( mpGlobalFuncIdx, 1 );
|
||||
mpTopIdx->AddSection( mpConstIdx , 1 );
|
||||
|
||||
// register reserved variables for index and description templates
|
||||
ScriptSection::RegisterTemplate( mTopTempl );
|
||||
ScriptSection::RegisterTemplate( mContentIdxTempl );
|
||||
ScriptSection::RegisterTemplate( mSuperContentTempl );
|
||||
ScriptSection::RegisterTemplate( mSubContentTempl );
|
||||
ScriptSection::RegisterTemplate( mOutLineTempl );
|
||||
ScriptSection::RegisterTemplate( mOutLine1Templ );
|
||||
ScriptSection::RegisterTemplate( mRefTempl );
|
||||
ScriptSection::RegisterTemplate( mDeadRefTempl );
|
||||
|
||||
// create the top-most (interfile) context
|
||||
mpFileBinderCtx = new spFile();
|
||||
|
||||
// the default script is HTML
|
||||
mTags = get_HTML_markup_tags();
|
||||
|
||||
mpParser = 0; // no default parser!
|
||||
}
|
||||
|
||||
void RipperDocGen::Init( SourceParserBase* pParser )
|
||||
{
|
||||
mpParser = pParser;
|
||||
}
|
||||
|
||||
RipperDocGen::~RipperDocGen()
|
||||
{
|
||||
delete mpFileBinderCtx;
|
||||
}
|
||||
|
||||
void RipperDocGen::AppendComments( spContext& fromContext, string& str )
|
||||
{
|
||||
if ( !fromContext.HasComments() ) return;
|
||||
|
||||
size_t start = str.length();
|
||||
|
||||
str += mTags[TAG_BOLD].end;
|
||||
str += mTags[TAG_PARAGRAPH].start;
|
||||
|
||||
MCommentListT& lst = fromContext.GetCommentList();
|
||||
|
||||
for( size_t i = 0; i != lst.size(); ++i )
|
||||
{
|
||||
|
||||
if ( i != 0 )
|
||||
|
||||
if ( lst[i]->StartsParagraph() )
|
||||
{
|
||||
str += mTags[TAG_PARAGRAPH].start;
|
||||
}
|
||||
|
||||
str += lst[i]->mText;
|
||||
}
|
||||
|
||||
// remove new lines, and insert paragraph breaks
|
||||
// if empty lines found
|
||||
|
||||
size_t len = str.length();
|
||||
|
||||
for( size_t n = start; n != len; ++n )
|
||||
|
||||
if ( str[n] == 10 ||
|
||||
str[n] == 13 )
|
||||
{
|
||||
if ( n + 2 < len )
|
||||
{
|
||||
if ( ( str[n] == 13 && str[n+1] == 10 && // FIXME:: quick-hack
|
||||
str[n+2] == 13 ) ||
|
||||
( str[n] == 10 && str[n+1] == 10 )
|
||||
)
|
||||
{
|
||||
str.insert( n + 1, "<p>" ); // FIXME:: quick-hack
|
||||
len += 3;
|
||||
}
|
||||
}
|
||||
|
||||
str[n] = ' ';
|
||||
}
|
||||
|
||||
str += mTags[TAG_PARAGRAPH].end;
|
||||
}
|
||||
|
||||
void RipperDocGen::AppendMulitilineStr( string& st, string& mlStr )
|
||||
{
|
||||
st = mTags[TAG_FIXED_FONT].start;
|
||||
st += mlStr;
|
||||
st += mTags[TAG_FIXED_FONT].end;
|
||||
}
|
||||
|
||||
void RipperDocGen::AppendHighlightedSource( string& st, string source )
|
||||
{
|
||||
// FIXME:: below should not be fixed :)
|
||||
char buf[1024*32];
|
||||
|
||||
// DBG:::
|
||||
ASSERT( source.length() + 1 < sizeof(buf) );
|
||||
|
||||
strcpy( buf, source.c_str() );
|
||||
|
||||
// highlight things
|
||||
mSrcPainter.Init();
|
||||
mSrcPainter.ProcessSource( buf, strlen(buf) );
|
||||
mSrcPainter.GetResultString( st, mTags );
|
||||
}
|
||||
|
||||
bool RipperDocGen::CheckIfUncommented( spContext& ctx, ScriptSection& toSect )
|
||||
{
|
||||
if ( ctx.HasComments() ) return 0;
|
||||
|
||||
toSect.AddReference(
|
||||
new ScriptSection( GetScopedName( ctx ), "", 0, &mDeadRefTempl )
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ScriptTemplate* RipperDocGen::GetRefTemplFor( spContext& ctx )
|
||||
{
|
||||
if ( ctx.HasComments() )
|
||||
|
||||
return &mRefTempl;
|
||||
else
|
||||
return &mDeadRefTempl;
|
||||
}
|
||||
|
||||
string RipperDocGen::GetScopedName( spContext& ofCtx )
|
||||
{
|
||||
if ( ofCtx.IsInFile() ) return ofCtx.GetName();
|
||||
else
|
||||
return ofCtx.GetOutterContext()->GetName() +
|
||||
"::" + ofCtx.GetName();
|
||||
}
|
||||
|
||||
void RipperDocGen::AddToCurrentClass( ScriptSection* pSection, spContext& ctx,
|
||||
const char* subSectionName )
|
||||
{
|
||||
string sName;
|
||||
|
||||
if ( ctx.mVisibility == SP_VIS_PROTECTED )
|
||||
|
||||
sName = "Protected members/";
|
||||
else
|
||||
if ( ctx.mVisibility == SP_VIS_PRIVATE )
|
||||
|
||||
sName = "Private members/";
|
||||
else
|
||||
sName = "Public members/";
|
||||
|
||||
sName += subSectionName;
|
||||
|
||||
ScriptSection* pSect = mpCurClassSect->GetSubsection( sName.c_str() );
|
||||
|
||||
if ( CheckIfUncommented( ctx, *pSect ) )
|
||||
{
|
||||
delete pSection;
|
||||
return;
|
||||
}
|
||||
|
||||
pSect->AddReference( pSection );
|
||||
|
||||
mpCurClassSect->AddSection( pSection );
|
||||
}
|
||||
|
||||
void RipperDocGen::LinkSuperClassRefs()
|
||||
{
|
||||
MMemberListT clLst;
|
||||
|
||||
// collect all classes in the context tree
|
||||
mpFileBinderCtx->GetContextList( clLst, SP_CTX_CLASS );
|
||||
|
||||
for( size_t i = 0; i != clLst.size(); ++i )
|
||||
{
|
||||
spClass& cl = *((spClass*)clLst[i]);
|
||||
|
||||
// FIXME:: why sometimes GetUserData() returns NULL?
|
||||
if ( !cl.GetUserData() )
|
||||
continue;
|
||||
|
||||
ScriptSection* pClSect = (ScriptSection*)cl.GetUserData();
|
||||
ScriptSection* pSuperSect = pClSect->GetSubsection("Derived from");
|
||||
|
||||
for( size_t n = 0; n != cl.mSuperClassNames.size(); ++n )
|
||||
{
|
||||
string& superClName = cl.mSuperClassNames[n];
|
||||
|
||||
spClass* pFound = NULL;
|
||||
|
||||
string* name;
|
||||
|
||||
for( size_t k = 0; k != clLst.size(); ++k )
|
||||
{
|
||||
name = &clLst[k]->GetName();
|
||||
|
||||
if ( clLst[k]->GetName() == superClName )
|
||||
{
|
||||
pFound = (spClass*)clLst[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !pFound )
|
||||
{
|
||||
ScriptSection* pNotFound =
|
||||
new ScriptSection( superClName, "", 0, &mDeadRefTempl );
|
||||
|
||||
pSuperSect->AddReference( pNotFound );
|
||||
}
|
||||
else
|
||||
if ( pFound->GetUserData() )
|
||||
|
||||
pSuperSect->AddReference(
|
||||
(ScriptSection*)pFound->GetUserData() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RipperDocGen::ProcessFile( const char* sourceFile )
|
||||
{
|
||||
cout << "Processing file " << sourceFile << "..." << endl;
|
||||
|
||||
spFile* pCtx = mpParser->ParseFile( sourceFile );
|
||||
|
||||
if ( pCtx == NULL )
|
||||
{
|
||||
cout << "Cannot open file " << sourceFile << ", skipped..." << endl;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VisitAll( *pCtx, TRUE );
|
||||
|
||||
mpFileBinderCtx->AddMember( pCtx );
|
||||
}
|
||||
|
||||
// implementations of "visiting procedures"
|
||||
|
||||
void RipperDocGen::VisitEnumeration( spEnumeration& en )
|
||||
{
|
||||
// FOR NOW:: do not reference "nameless" enums
|
||||
if ( en.GetName() == "" ) return;
|
||||
|
||||
if ( CheckIfUncommented( en, *mpEnumIdx ) )
|
||||
return;
|
||||
|
||||
string body;
|
||||
body += mTags[TAG_BOLD].start;
|
||||
|
||||
AppendMulitilineStr( body, en.mEnumContent );
|
||||
|
||||
body += mTags[TAG_BOLD].end;
|
||||
|
||||
string line;
|
||||
AppendHighlightedSource( line, body );
|
||||
AppendComments( en, line );
|
||||
|
||||
mpEnumIdx->AddSection(
|
||||
new ScriptSection( en.GetName(), line,
|
||||
&mSubContentTempl,
|
||||
GetRefTemplFor( en ) ), 1
|
||||
);
|
||||
}
|
||||
|
||||
void RipperDocGen::VisitTypeDef( spTypeDef& td )
|
||||
{
|
||||
if ( CheckIfUncommented( td, *mpTypeDefIdx ) )
|
||||
return;
|
||||
|
||||
string body;
|
||||
body += mTags[TAG_BOLD].start;
|
||||
body += "typdef ";
|
||||
body += mTags[TAG_BOLD].end;
|
||||
|
||||
AppendMulitilineStr( body, td.mOriginalType );
|
||||
body += td.mOriginalType;
|
||||
body += ' ';
|
||||
|
||||
body += mTags[TAG_BOLD].start;
|
||||
body += td.GetName();
|
||||
body += mTags[TAG_BOLD].end;
|
||||
|
||||
string line;
|
||||
AppendHighlightedSource( line, body );
|
||||
AppendComments( td, line );
|
||||
|
||||
mpTypeDefIdx->AddSection(
|
||||
new ScriptSection( td.GetName(), line,
|
||||
&mSubContentTempl,
|
||||
GetRefTemplFor( td ) ), TRUE
|
||||
);
|
||||
}
|
||||
|
||||
void RipperDocGen::VisitPreprocessorLine( spPreprocessorLine& pd )
|
||||
{
|
||||
if ( pd.mDefType != SP_PREP_DEF_REDEFINE_SYMBOL )
|
||||
|
||||
return;
|
||||
|
||||
if ( CheckIfUncommented( pd, *mpMacroIdx ) )
|
||||
return;
|
||||
|
||||
string body;
|
||||
body += mTags[TAG_FIXED_FONT].start;
|
||||
|
||||
string coloredLine = pd.mLine;
|
||||
AppendHighlightedSource( coloredLine, pd.mLine );
|
||||
|
||||
AppendMulitilineStr( body, coloredLine );
|
||||
|
||||
body += mTags[TAG_FIXED_FONT].end;
|
||||
|
||||
AppendComments( pd, body );
|
||||
|
||||
mpMacroIdx->AddSection(
|
||||
new ScriptSection( pd.GetName(), body,
|
||||
&mSubContentTempl,
|
||||
GetRefTemplFor( pd ) ), TRUE
|
||||
);
|
||||
}
|
||||
|
||||
void RipperDocGen::VisitClass( spClass& cl )
|
||||
{
|
||||
// FOR NOW:: do not document nested classes -
|
||||
// nicier visiting method yet needed
|
||||
|
||||
if ( cl.IsInClass() )
|
||||
{
|
||||
SkipChildren(); // spVisitor's method
|
||||
return;
|
||||
}
|
||||
|
||||
string body;
|
||||
AppendComments( cl, body );
|
||||
|
||||
mpCurClassSect =
|
||||
new ScriptSection( cl.GetName(), body, &mSuperContentTempl, &mRefTempl );
|
||||
|
||||
// set up reference in the class context, pointing back
|
||||
// to the section where this class is represented
|
||||
cl.SetUserData( mpCurClassSect );
|
||||
|
||||
ScriptSection* pSuper = new ScriptSection( "Derived from" ,"", &mOutLine1Templ,0, 1 );
|
||||
|
||||
ScriptSection* pPublic = new ScriptSection( "Public members" ,"", &mOutLineTempl,0, 1 );
|
||||
ScriptSection* pProtected = new ScriptSection( "Protected members" ,"", &mOutLineTempl,0, 1 );
|
||||
ScriptSection* pPrivate = new ScriptSection( "Private members" ,"", &mOutLineTempl,0, 1 );
|
||||
|
||||
pPublic->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ, 0, 1 ) );
|
||||
pPublic->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ, 0, 1 ) );
|
||||
|
||||
|
||||
pProtected->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ, 0, 1 ) );
|
||||
pProtected->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ, 0, 1 ) );
|
||||
|
||||
|
||||
pPrivate->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ, 0, 1 ) );
|
||||
pPrivate->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ, 0, 1 ) );
|
||||
|
||||
mpCurClassSect->AddSection( pSuper );
|
||||
mpCurClassSect->AddSection( pPublic );
|
||||
mpCurClassSect->AddSection( pProtected );
|
||||
mpCurClassSect->AddSection( pPrivate );
|
||||
|
||||
mpClassIdx->AddSection( mpCurClassSect, TRUE );
|
||||
}
|
||||
|
||||
void RipperDocGen::VisitAttribute( spAttribute& attr )
|
||||
{
|
||||
string body;
|
||||
body += mTags[TAG_BOLD].start;
|
||||
body += attr.mType;
|
||||
body += mTags[TAG_BOLD].end;
|
||||
|
||||
body += mTags[TAG_ITALIC].start;
|
||||
body += ' ';
|
||||
body += attr.GetName();
|
||||
body += mTags[TAG_ITALIC].end;
|
||||
|
||||
string line;
|
||||
AppendHighlightedSource( line, body );
|
||||
AppendComments( attr, line );
|
||||
|
||||
ScriptSection* pSection =
|
||||
new ScriptSection( GetScopedName( attr ), line,
|
||||
&mSubContentTempl,
|
||||
GetRefTemplFor( attr ) );
|
||||
|
||||
if ( attr.mIsConstant )
|
||||
|
||||
mpConstIdx->AddSection( pSection, TRUE );
|
||||
|
||||
else
|
||||
if ( !attr.IsInClass() )
|
||||
{
|
||||
if ( CheckIfUncommented( attr, *mpGlobalVarsIdx ) )
|
||||
return;
|
||||
|
||||
mpGlobalVarsIdx->AddSection( pSection, TRUE );
|
||||
}
|
||||
else
|
||||
|
||||
AddToCurrentClass( pSection, attr, "Attributes" );
|
||||
}
|
||||
|
||||
void RipperDocGen::VisitOperation( spOperation& op )
|
||||
{
|
||||
string body;
|
||||
|
||||
AppendHighlightedSource( body, op.GetFullName(mTags) );
|
||||
|
||||
AppendComments( op, body );
|
||||
|
||||
ScriptSection* pSection =
|
||||
new ScriptSection( GetScopedName( op ), body,
|
||||
&mSubContentTempl,
|
||||
GetRefTemplFor( op ) );
|
||||
|
||||
if ( !op.IsInClass() )
|
||||
{
|
||||
if ( CheckIfUncommented( op, *mpGlobalFuncIdx ) )
|
||||
return;
|
||||
|
||||
mpGlobalFuncIdx->AddSection( pSection, 1 );
|
||||
}
|
||||
else
|
||||
AddToCurrentClass( pSection, op, "Operations" );
|
||||
}
|
||||
|
||||
bool RipperDocGen::OnSaveDocument( ScriptStream& stm )
|
||||
{
|
||||
LinkSuperClassRefs();
|
||||
|
||||
// FOR NOW:: doesn't work yet
|
||||
//mpTopIdx->RemoveEmptySections();
|
||||
|
||||
return 1; // saving can proceed now
|
||||
}
|
||||
|
Reference in New Issue
Block a user