1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleskandars Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
23 #include "docripper.h"
33 // ***** currently only HTML versions of variouse templates available ***** //
35 static const char* HTM_TopTempl
=
37 "<html><body bgcolor=#FFFFFF>\n\
38 \n\n<!------ Automatically Generated by \"wxDocRipper\"------->\n\n\n\
39 <p><h2>$(NAME)</h2><p>\n\
45 static const char* HTM_ContentIdxTempl
=
48 <a name=\"r$(ID)_$(NAME)\">\n\
50 <h2><p>$(NAME)<p></h2>\
56 static const char* HTM_SuperContentTempl
=
59 <a name=\"r$(ID)_$(NAME)\">\n\
61 <p><h2>$(NAME)<p></h2>\
65 static const char* HTM_SubContentTempl
=
68 <a name=\"r$(ID)_$(NAME)\">\n\
70 <p><h3>$(NAME)<p></h3>\
74 static const char* HTM_OutLineTempl
=
78 <b><font color=\"#FF0000\">$(NAME)</font></b><p>\n\
81 static const char* HTM_OutLine1Templ
=
85 <b><i><font color=\"#101010\">$(NAME)</font></i></b>\n\
91 static const char* HTM_RefTempl
=
94 <li><a href=\"#r$(ID)_$(NAME)\">$(NAME)</A>\n\
97 static const char* HTM_DeadRefTempl
=
103 /***** Implementation for class RipperDocGen *****/
105 RipperDocGen::RipperDocGen()
107 : mTopTempl ( HTM_TopTempl
),
108 mContentIdxTempl ( HTM_ContentIdxTempl
),
109 mSuperContentTempl( HTM_SuperContentTempl
),
110 mSubContentTempl ( HTM_SubContentTempl
),
111 mOutLineTempl ( HTM_OutLineTempl
),
112 mOutLine1Templ ( HTM_OutLine1Templ
),
114 mRefTempl ( HTM_RefTempl
),
115 mDeadRefTempl ( HTM_DeadRefTempl
),
118 { // topIndex is not referenced
119 mpTopIdx
= new ScriptSection( "Source Code Contents" , "", &mTopTempl
, 0 );
120 mpClassIdx
= new ScriptSection( "Classes Reference" , "", &mContentIdxTempl
, &mRefTempl
);
121 mpEnumIdx
= new ScriptSection( "Enumerations Reference" , "", &mContentIdxTempl
, &mRefTempl
);
122 mpTypeDefIdx
= new ScriptSection( "Type Definitions Reference" , "", &mContentIdxTempl
, &mRefTempl
);
123 mpMacroIdx
= new ScriptSection( "Macros Reference" , "", &mContentIdxTempl
, &mRefTempl
);
124 mpGlobalVarsIdx
= new ScriptSection( "Global Variables Reference" , "", &mContentIdxTempl
, &mRefTempl
);
125 mpGlobalFuncIdx
= new ScriptSection( "Global Functions Reference", "", &mContentIdxTempl
, &mRefTempl
);
126 mpConstIdx
= new ScriptSection( "Constants Reference" , "", &mContentIdxTempl
, &mRefTempl
);
128 // assemble top index
129 mpTopIdx
->AddSection( mpClassIdx
, 1 );
130 mpTopIdx
->AddSection( mpEnumIdx
, 1 );
131 mpTopIdx
->AddSection( mpTypeDefIdx
, 1 );
132 mpTopIdx
->AddSection( mpMacroIdx
, 1 );
133 mpTopIdx
->AddSection( mpGlobalVarsIdx
, 1 );
134 mpTopIdx
->AddSection( mpGlobalFuncIdx
, 1 );
135 mpTopIdx
->AddSection( mpConstIdx
, 1 );
137 // register reserved variables for index and description templates
138 ScriptSection::RegisterTemplate( mTopTempl
);
139 ScriptSection::RegisterTemplate( mContentIdxTempl
);
140 ScriptSection::RegisterTemplate( mSuperContentTempl
);
141 ScriptSection::RegisterTemplate( mSubContentTempl
);
142 ScriptSection::RegisterTemplate( mOutLineTempl
);
143 ScriptSection::RegisterTemplate( mOutLine1Templ
);
144 ScriptSection::RegisterTemplate( mRefTempl
);
145 ScriptSection::RegisterTemplate( mDeadRefTempl
);
147 // create the top-most (interfile) context
148 mpFileBinderCtx
= new spFile();
150 // the default script is HTML
151 mTags
= get_HTML_markup_tags();
153 mpParser
= 0; // no default parser!
156 void RipperDocGen::Init( SourceParserBase
* pParser
)
161 RipperDocGen::~RipperDocGen()
163 delete mpFileBinderCtx
;
166 void RipperDocGen::AppendComments( spContext
& fromContext
, string
& str
)
168 if ( !fromContext
.HasComments() ) return;
170 size_t start
= str
.length();
172 str
+= mTags
[TAG_BOLD
].end
;
173 str
+= mTags
[TAG_PARAGRAPH
].start
;
175 MCommentListT
& lst
= fromContext
.GetCommentList();
177 for( size_t i
= 0; i
!= lst
.size(); ++i
)
182 if ( lst
[i
]->StartsParagraph() )
184 str
+= mTags
[TAG_PARAGRAPH
].start
;
188 str
+= lst
[i
]->mText
;
191 // remove new lines, and insert paragraph breaks
193 // if empty lines found
195 size_t len
= str
.length();
197 for( size_t n
= start
; n
!= len
; ++n
)
208 if ( ( str
[n
] == 13 && str
[n
+1] == 10 && // FIXME:: quick-hack
212 ( str
[n
] == 10 && str
[n
+1] == 10 )
218 str
.insert( n
+ 1, "<p>" ); // FIXME:: quick-hack
233 str
+= mTags
[TAG_PARAGRAPH
].end
;
236 void RipperDocGen::AppendMulitilineStr( string
& st
, string
& mlStr
)
238 st
= mTags
[TAG_FIXED_FONT
].start
;
240 st
+= mTags
[TAG_FIXED_FONT
].end
;
243 void RipperDocGen::AppendHighlightedSource( string
& st
, string source
)
245 // FIXME:: below should not be fixed :)
249 // ASSERT( source.length() + 1 < sizeof(buf) );
251 strcpy( buf
, source
.c_str() );
255 mSrcPainter
.ProcessSource( buf
, strlen(buf
) );
256 mSrcPainter
.GetResultString( st
, mTags
);
259 bool RipperDocGen::CheckIfUncommented( spContext
& ctx
, ScriptSection
& toSect
)
261 if ( ctx
.HasComments() ) return 0;
264 new ScriptSection( GetScopedName( ctx
), "", 0, &mDeadRefTempl
)
270 ScriptTemplate
* RipperDocGen::GetRefTemplFor( spContext
& ctx
)
272 if ( ctx
.HasComments() )
276 return &mDeadRefTempl
;
279 string
RipperDocGen::GetScopedName( spContext
& ofCtx
)
281 if ( ofCtx
.IsInFile() ) return ofCtx
.GetName();
283 return ofCtx
.GetOutterContext()->GetName() +
284 "::" + ofCtx
.GetName();
287 void RipperDocGen::AddToCurrentClass( ScriptSection
* pSection
, spContext
& ctx
,
288 const char* subSectionName
)
292 if ( ctx
.mVisibility
== SP_VIS_PROTECTED
)
294 sName
= "Protected members/";
296 if ( ctx
.mVisibility
== SP_VIS_PRIVATE
)
298 sName
= "Private members/";
300 sName
= "Public members/";
302 sName
+= subSectionName
;
304 ScriptSection
* pSect
= mpCurClassSect
->GetSubsection( sName
.c_str() );
306 if ( CheckIfUncommented( ctx
, *pSect
) )
312 pSect
->AddReference( pSection
);
314 mpCurClassSect
->AddSection( pSection
);
317 void RipperDocGen::LinkSuperClassRefs()
321 // collect all classes in the context tree
322 mpFileBinderCtx
->GetContextList( clLst
, SP_CTX_CLASS
);
324 for( size_t i
= 0; i
!= clLst
.size(); ++i
)
326 spClass
& cl
= *((spClass
*)clLst
[i
]);
328 // FIXME:: why sometimes GetUserData() returns NULL?
329 if ( !cl
.GetUserData() )
332 ScriptSection
* pClSect
= (ScriptSection
*)cl
.GetUserData();
333 ScriptSection
* pSuperSect
= pClSect
->GetSubsection("Derived from");
335 for( size_t n
= 0; n
!= cl
.mSuperClassNames
.size(); ++n
)
337 string
& superClName
= cl
.mSuperClassNames
[n
];
339 spClass
* pFound
= NULL
;
343 for( size_t k
= 0; k
!= clLst
.size(); ++k
)
345 name
= &clLst
[k
]->GetName();
347 if ( clLst
[k
]->GetName() == superClName
)
349 pFound
= (spClass
*)clLst
[k
];
356 ScriptSection
* pNotFound
=
357 new ScriptSection( superClName
, "", 0, &mDeadRefTempl
);
359 pSuperSect
->AddReference( pNotFound
);
362 if ( pFound
->GetUserData() )
364 pSuperSect
->AddReference(
365 (ScriptSection
*)pFound
->GetUserData() );
370 void RipperDocGen::ProcessFile( const char* sourceFile
)
372 cout
<< "Processing file " << sourceFile
<< "..." << endl
;
374 spFile
* pCtx
= mpParser
->ParseFile( sourceFile
);
378 cout
<< "Cannot open file " << sourceFile
<< ", skipped..." << endl
;
383 VisitAll( *pCtx
, TRUE
);
385 mpFileBinderCtx
->AddMember( pCtx
);
388 // implementations of "visiting procedures"
390 void RipperDocGen::VisitEnumeration( spEnumeration
& en
)
392 // FOR NOW:: do not reference "nameless" enums
393 if ( en
.GetName() == "" ) return;
395 if ( CheckIfUncommented( en
, *mpEnumIdx
) )
399 body
+= mTags
[TAG_BOLD
].start
;
401 AppendMulitilineStr( body
, en
.mEnumContent
);
403 body
+= mTags
[TAG_BOLD
].end
;
406 AppendHighlightedSource( line
, body
);
407 AppendComments( en
, line
);
409 mpEnumIdx
->AddSection(
410 new ScriptSection( en
.GetName(), line
,
412 GetRefTemplFor( en
) ), 1
416 void RipperDocGen::VisitTypeDef( spTypeDef
& td
)
418 if ( CheckIfUncommented( td
, *mpTypeDefIdx
) )
422 body
+= mTags
[TAG_BOLD
].start
;
424 body
+= mTags
[TAG_BOLD
].end
;
426 AppendMulitilineStr( body
, td
.mOriginalType
);
427 body
+= td
.mOriginalType
;
430 body
+= mTags
[TAG_BOLD
].start
;
431 body
+= td
.GetName();
432 body
+= mTags
[TAG_BOLD
].end
;
435 AppendHighlightedSource( line
, body
);
436 AppendComments( td
, line
);
438 mpTypeDefIdx
->AddSection(
439 new ScriptSection( td
.GetName(), line
,
441 GetRefTemplFor( td
) ), TRUE
445 void RipperDocGen::VisitPreprocessorLine( spPreprocessorLine
& pd
)
447 if ( pd
.mDefType
!= SP_PREP_DEF_REDEFINE_SYMBOL
)
454 if ( CheckIfUncommented( pd
, *mpMacroIdx
) )
458 body
+= mTags
[TAG_FIXED_FONT
].start
;
460 string coloredLine
= pd
.mLine
;
461 AppendHighlightedSource( coloredLine
, pd
.mLine
);
463 AppendMulitilineStr( body
, coloredLine
);
465 body
+= mTags
[TAG_FIXED_FONT
].end
;
467 AppendComments( pd
, body
);
469 mpMacroIdx
->AddSection(
470 new ScriptSection( pd
.GetName(), body
,
472 GetRefTemplFor( pd
) ), TRUE
476 void RipperDocGen::VisitClass( spClass
& cl
)
478 // FOR NOW:: do not document nested classes -
479 // nicier visiting method yet needed
481 if ( cl
.IsInClass() )
483 SkipChildren(); // spVisitor's method
488 AppendComments( cl
, body
);
491 new ScriptSection( cl
.GetName(), body
, &mSuperContentTempl
, &mRefTempl
);
493 // set up reference in the class context, pointing back
494 // to the section where this class is represented
495 cl
.SetUserData( mpCurClassSect
);
497 ScriptSection
* pSuper
= new ScriptSection( "Derived from" ,"", &mOutLine1Templ
,0, 1 );
499 ScriptSection
* pPublic
= new ScriptSection( "Public members" ,"", &mOutLineTempl
,0, 1 );
500 ScriptSection
* pProtected
= new ScriptSection( "Protected members" ,"", &mOutLineTempl
,0, 1 );
501 ScriptSection
* pPrivate
= new ScriptSection( "Private members" ,"", &mOutLineTempl
,0, 1 );
503 pPublic
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
504 pPublic
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
507 pProtected
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
508 pProtected
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
511 pPrivate
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
512 pPrivate
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
514 mpCurClassSect
->AddSection( pSuper
);
515 mpCurClassSect
->AddSection( pPublic
);
516 mpCurClassSect
->AddSection( pProtected
);
517 mpCurClassSect
->AddSection( pPrivate
);
519 mpClassIdx
->AddSection( mpCurClassSect
, TRUE
);
522 void RipperDocGen::VisitAttribute( spAttribute
& attr
)
525 body
+= mTags
[TAG_BOLD
].start
;
527 body
+= mTags
[TAG_BOLD
].end
;
529 body
+= mTags
[TAG_ITALIC
].start
;
531 body
+= attr
.GetName();
532 body
+= mTags
[TAG_ITALIC
].end
;
535 AppendHighlightedSource( line
, body
);
536 AppendComments( attr
, line
);
538 ScriptSection
* pSection
=
539 new ScriptSection( GetScopedName( attr
), line
,
541 GetRefTemplFor( attr
) );
543 if ( attr
.mIsConstant
)
545 mpConstIdx
->AddSection( pSection
, TRUE
);
548 if ( !attr
.IsInClass() )
550 if ( CheckIfUncommented( attr
, *mpGlobalVarsIdx
) )
553 mpGlobalVarsIdx
->AddSection( pSection
, TRUE
);
557 AddToCurrentClass( pSection
, attr
, "Attributes" );
560 void RipperDocGen::VisitOperation( spOperation
& op
)
564 AppendHighlightedSource( body
, op
.GetFullName(mTags
) );
566 AppendComments( op
, body
);
568 ScriptSection
* pSection
=
569 new ScriptSection( GetScopedName( op
), body
,
571 GetRefTemplFor( op
) );
573 if ( !op
.IsInClass() )
575 if ( CheckIfUncommented( op
, *mpGlobalFuncIdx
) )
578 mpGlobalFuncIdx
->AddSection( pSection
, 1 );
581 AddToCurrentClass( pSection
, op
, "Operations" );
584 bool RipperDocGen::OnSaveDocument( ScriptStream
& stm
)
586 LinkSuperClassRefs();
588 // FOR NOW:: doesn't work yet
589 //mpTopIdx->RemoveEmptySections();
591 return 1; // saving can proceed now