home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
wxos2233.zip
/
wxOS2-2_3_3.zip
/
wxWindows-2.3.3
/
utils
/
HelpGen
/
src
/
docripper.cpp
< prev
next >
Wrap
Text File
|
2002-01-18
|
14KB
|
594 lines
/////////////////////////////////////////////////////////////////////////////
// Name: No names yet.
// Purpose: Contrib. demo
// Author: Aleksandras Gluchovas
// Modified by:
// Created: 22/09/98
// RCS-ID: $Id: docripper.cpp,v 1.3 2002/01/15 14:49:31 GT Exp $
// 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"
#if wxUSE_IOSTREAMH
#include <iostream.h>
#else
#include <iostream>
#endif
// 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
}