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"
29 // ***** currently only HTML versions of variouse templates available ***** //
31 static const char* HTM_TopTempl
=
33 "<html><body bgcolor=#FFFFFF>\n\
34 \n\n<!------ Automatically Generated by \"wxDocRipper\"------->\n\n\n\
35 <p><h2>$(NAME)</h2><p>\n\
41 static const char* HTM_ContentIdxTempl
=
44 <a name=\"r$(ID)_$(NAME)\">\n\
46 <h2><p>$(NAME)<p></h2>\
52 static const char* HTM_SuperContentTempl
=
55 <a name=\"r$(ID)_$(NAME)\">\n\
57 <p><h2>$(NAME)<p></h2>\
61 static const char* HTM_SubContentTempl
=
64 <a name=\"r$(ID)_$(NAME)\">\n\
66 <p><h3>$(NAME)<p></h3>\
70 static const char* HTM_OutLineTempl
=
74 <b><font color=\"#FF0000\">$(NAME)</font></b><p>\n\
77 static const char* HTM_OutLine1Templ
=
81 <b><i><font color=\"#101010\">$(NAME)</font></i></b>\n\
87 static const char* HTM_RefTempl
=
90 <li><a href=\"#r$(ID)_$(NAME)\">$(NAME)</A>\n\
93 static const char* HTM_DeadRefTempl
=
99 /***** Implementation for class RipperDocGen *****/
101 RipperDocGen::RipperDocGen()
103 : mTopTempl ( HTM_TopTempl
),
104 mContentIdxTempl ( HTM_ContentIdxTempl
),
105 mSuperContentTempl( HTM_SuperContentTempl
),
106 mSubContentTempl ( HTM_SubContentTempl
),
107 mOutLineTempl ( HTM_OutLineTempl
),
108 mOutLine1Templ ( HTM_OutLine1Templ
),
110 mRefTempl ( HTM_RefTempl
),
111 mDeadRefTempl ( HTM_DeadRefTempl
),
114 { // topIndex is not referenced
115 mpTopIdx
= new ScriptSection( "Source Code Contents" , "", &mTopTempl
, 0 );
116 mpClassIdx
= new ScriptSection( "Classes Reference" , "", &mContentIdxTempl
, &mRefTempl
);
117 mpEnumIdx
= new ScriptSection( "Enumerations Reference" , "", &mContentIdxTempl
, &mRefTempl
);
118 mpTypeDefIdx
= new ScriptSection( "Type Definitions Reference" , "", &mContentIdxTempl
, &mRefTempl
);
119 mpMacroIdx
= new ScriptSection( "Macros Reference" , "", &mContentIdxTempl
, &mRefTempl
);
120 mpGlobalVarsIdx
= new ScriptSection( "Global Variables Reference" , "", &mContentIdxTempl
, &mRefTempl
);
121 mpGlobalFuncIdx
= new ScriptSection( "Global Functions Reference", "", &mContentIdxTempl
, &mRefTempl
);
122 mpConstIdx
= new ScriptSection( "Constants Reference" , "", &mContentIdxTempl
, &mRefTempl
);
124 // assemble top index
125 mpTopIdx
->AddSection( mpClassIdx
, 1 );
126 mpTopIdx
->AddSection( mpEnumIdx
, 1 );
127 mpTopIdx
->AddSection( mpTypeDefIdx
, 1 );
128 mpTopIdx
->AddSection( mpMacroIdx
, 1 );
129 mpTopIdx
->AddSection( mpGlobalVarsIdx
, 1 );
130 mpTopIdx
->AddSection( mpGlobalFuncIdx
, 1 );
131 mpTopIdx
->AddSection( mpConstIdx
, 1 );
133 // register reserved variables for index and description templates
134 ScriptSection::RegisterTemplate( mTopTempl
);
135 ScriptSection::RegisterTemplate( mContentIdxTempl
);
136 ScriptSection::RegisterTemplate( mSuperContentTempl
);
137 ScriptSection::RegisterTemplate( mSubContentTempl
);
138 ScriptSection::RegisterTemplate( mOutLineTempl
);
139 ScriptSection::RegisterTemplate( mOutLine1Templ
);
140 ScriptSection::RegisterTemplate( mRefTempl
);
141 ScriptSection::RegisterTemplate( mDeadRefTempl
);
143 // create the top-most (interfile) context
144 mpFileBinderCtx
= new spFile();
146 // the default script is HTML
147 mTags
= get_HTML_markup_tags();
149 mpParser
= 0; // no default parser!
152 void RipperDocGen::Init( SourceParserBase
* pParser
)
157 RipperDocGen::~RipperDocGen()
159 delete mpFileBinderCtx
;
162 void RipperDocGen::AppendComments( spContext
& fromContext
, string
& str
)
164 if ( !fromContext
.HasComments() ) return;
166 size_t start
= str
.length();
168 str
+= mTags
[TAG_BOLD
].end
;
169 str
+= mTags
[TAG_PARAGRAPH
].start
;
171 MCommentListT
& lst
= fromContext
.GetCommentList();
173 for( size_t i
= 0; i
!= lst
.size(); ++i
)
178 if ( lst
[i
]->StartsParagraph() )
180 str
+= mTags
[TAG_PARAGRAPH
].start
;
183 str
+= lst
[i
]->mText
;
186 // remove new lines, and insert paragraph breaks
187 // if empty lines found
189 size_t len
= str
.length();
191 for( size_t n
= start
; n
!= len
; ++n
)
198 if ( ( str
[n
] == 13 && str
[n
+1] == 10 && // FIXME:: quick-hack
200 ( str
[n
] == 10 && str
[n
+1] == 10 )
203 str
.insert( n
+ 1, "<p>" ); // FIXME:: quick-hack
211 str
+= mTags
[TAG_PARAGRAPH
].end
;
214 void RipperDocGen::AppendMulitilineStr( string
& st
, string
& mlStr
)
216 st
= mTags
[TAG_FIXED_FONT
].start
;
218 st
+= mTags
[TAG_FIXED_FONT
].end
;
221 void RipperDocGen::AppendHighlightedSource( string
& st
, string source
)
223 // FIXME:: below should not be fixed :)
227 // ASSERT( source.length() + 1 < sizeof(buf) );
229 strcpy( buf
, source
.c_str() );
233 mSrcPainter
.ProcessSource( buf
, strlen(buf
) );
234 mSrcPainter
.GetResultString( st
, mTags
);
237 bool RipperDocGen::CheckIfUncommented( spContext
& ctx
, ScriptSection
& toSect
)
239 if ( ctx
.HasComments() ) return 0;
242 new ScriptSection( GetScopedName( ctx
), "", 0, &mDeadRefTempl
)
248 ScriptTemplate
* RipperDocGen::GetRefTemplFor( spContext
& ctx
)
250 if ( ctx
.HasComments() )
254 return &mDeadRefTempl
;
257 string
RipperDocGen::GetScopedName( spContext
& ofCtx
)
259 if ( ofCtx
.IsInFile() ) return ofCtx
.GetName();
261 return ofCtx
.GetOutterContext()->GetName() +
262 "::" + ofCtx
.GetName();
265 void RipperDocGen::AddToCurrentClass( ScriptSection
* pSection
, spContext
& ctx
,
266 const char* subSectionName
)
270 if ( ctx
.mVisibility
== SP_VIS_PROTECTED
)
272 sName
= "Protected members/";
274 if ( ctx
.mVisibility
== SP_VIS_PRIVATE
)
276 sName
= "Private members/";
278 sName
= "Public members/";
280 sName
+= subSectionName
;
282 ScriptSection
* pSect
= mpCurClassSect
->GetSubsection( sName
.c_str() );
284 if ( CheckIfUncommented( ctx
, *pSect
) )
290 pSect
->AddReference( pSection
);
292 mpCurClassSect
->AddSection( pSection
);
295 void RipperDocGen::LinkSuperClassRefs()
299 // collect all classes in the context tree
300 mpFileBinderCtx
->GetContextList( clLst
, SP_CTX_CLASS
);
302 for( size_t i
= 0; i
!= clLst
.size(); ++i
)
304 spClass
& cl
= *((spClass
*)clLst
[i
]);
306 // FIXME:: why sometimes GetUserData() returns NULL?
307 if ( !cl
.GetUserData() )
310 ScriptSection
* pClSect
= (ScriptSection
*)cl
.GetUserData();
311 ScriptSection
* pSuperSect
= pClSect
->GetSubsection("Derived from");
313 for( size_t n
= 0; n
!= cl
.mSuperClassNames
.size(); ++n
)
315 string
& superClName
= cl
.mSuperClassNames
[n
];
317 spClass
* pFound
= NULL
;
321 for( size_t k
= 0; k
!= clLst
.size(); ++k
)
323 name
= &clLst
[k
]->GetName();
325 if ( clLst
[k
]->GetName() == superClName
)
327 pFound
= (spClass
*)clLst
[k
];
334 ScriptSection
* pNotFound
=
335 new ScriptSection( superClName
, "", 0, &mDeadRefTempl
);
337 pSuperSect
->AddReference( pNotFound
);
340 if ( pFound
->GetUserData() )
342 pSuperSect
->AddReference(
343 (ScriptSection
*)pFound
->GetUserData() );
348 void RipperDocGen::ProcessFile( const char* sourceFile
)
350 cout
<< "Processing file " << sourceFile
<< "..." << endl
;
352 spFile
* pCtx
= mpParser
->ParseFile( sourceFile
);
356 cout
<< "Cannot open file " << sourceFile
<< ", skipped..." << endl
;
361 VisitAll( *pCtx
, TRUE
);
363 mpFileBinderCtx
->AddMember( pCtx
);
366 // implementations of "visiting procedures"
368 void RipperDocGen::VisitEnumeration( spEnumeration
& en
)
370 // FOR NOW:: do not reference "nameless" enums
371 if ( en
.GetName() == "" ) return;
373 if ( CheckIfUncommented( en
, *mpEnumIdx
) )
377 body
+= mTags
[TAG_BOLD
].start
;
379 AppendMulitilineStr( body
, en
.mEnumContent
);
381 body
+= mTags
[TAG_BOLD
].end
;
384 AppendHighlightedSource( line
, body
);
385 AppendComments( en
, line
);
387 mpEnumIdx
->AddSection(
388 new ScriptSection( en
.GetName(), line
,
390 GetRefTemplFor( en
) ), 1
394 void RipperDocGen::VisitTypeDef( spTypeDef
& td
)
396 if ( CheckIfUncommented( td
, *mpTypeDefIdx
) )
400 body
+= mTags
[TAG_BOLD
].start
;
402 body
+= mTags
[TAG_BOLD
].end
;
404 AppendMulitilineStr( body
, td
.mOriginalType
);
405 body
+= td
.mOriginalType
;
408 body
+= mTags
[TAG_BOLD
].start
;
409 body
+= td
.GetName();
410 body
+= mTags
[TAG_BOLD
].end
;
413 AppendHighlightedSource( line
, body
);
414 AppendComments( td
, line
);
416 mpTypeDefIdx
->AddSection(
417 new ScriptSection( td
.GetName(), line
,
419 GetRefTemplFor( td
) ), TRUE
423 void RipperDocGen::VisitPreprocessorLine( spPreprocessorLine
& pd
)
425 if ( pd
.mDefType
!= SP_PREP_DEF_REDEFINE_SYMBOL
)
429 if ( CheckIfUncommented( pd
, *mpMacroIdx
) )
433 body
+= mTags
[TAG_FIXED_FONT
].start
;
435 string coloredLine
= pd
.mLine
;
436 AppendHighlightedSource( coloredLine
, pd
.mLine
);
438 AppendMulitilineStr( body
, coloredLine
);
440 body
+= mTags
[TAG_FIXED_FONT
].end
;
442 AppendComments( pd
, body
);
444 mpMacroIdx
->AddSection(
445 new ScriptSection( pd
.GetName(), body
,
447 GetRefTemplFor( pd
) ), TRUE
451 void RipperDocGen::VisitClass( spClass
& cl
)
453 // FOR NOW:: do not document nested classes -
454 // nicier visiting method yet needed
456 if ( cl
.IsInClass() )
458 SkipChildren(); // spVisitor's method
463 AppendComments( cl
, body
);
466 new ScriptSection( cl
.GetName(), body
, &mSuperContentTempl
, &mRefTempl
);
468 // set up reference in the class context, pointing back
469 // to the section where this class is represented
470 cl
.SetUserData( mpCurClassSect
);
472 ScriptSection
* pSuper
= new ScriptSection( "Derived from" ,"", &mOutLine1Templ
,0, 1 );
474 ScriptSection
* pPublic
= new ScriptSection( "Public members" ,"", &mOutLineTempl
,0, 1 );
475 ScriptSection
* pProtected
= new ScriptSection( "Protected members" ,"", &mOutLineTempl
,0, 1 );
476 ScriptSection
* pPrivate
= new ScriptSection( "Private members" ,"", &mOutLineTempl
,0, 1 );
478 pPublic
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
479 pPublic
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
482 pProtected
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
483 pProtected
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
486 pPrivate
->AddSection( new ScriptSection( "Operations", "", &mOutLine1Templ
, 0, 1 ) );
487 pPrivate
->AddSection( new ScriptSection( "Attributes", "", &mOutLine1Templ
, 0, 1 ) );
489 mpCurClassSect
->AddSection( pSuper
);
490 mpCurClassSect
->AddSection( pPublic
);
491 mpCurClassSect
->AddSection( pProtected
);
492 mpCurClassSect
->AddSection( pPrivate
);
494 mpClassIdx
->AddSection( mpCurClassSect
, TRUE
);
497 void RipperDocGen::VisitAttribute( spAttribute
& attr
)
500 body
+= mTags
[TAG_BOLD
].start
;
502 body
+= mTags
[TAG_BOLD
].end
;
504 body
+= mTags
[TAG_ITALIC
].start
;
506 body
+= attr
.GetName();
507 body
+= mTags
[TAG_ITALIC
].end
;
510 AppendHighlightedSource( line
, body
);
511 AppendComments( attr
, line
);
513 ScriptSection
* pSection
=
514 new ScriptSection( GetScopedName( attr
), line
,
516 GetRefTemplFor( attr
) );
518 if ( attr
.mIsConstant
)
520 mpConstIdx
->AddSection( pSection
, TRUE
);
523 if ( !attr
.IsInClass() )
525 if ( CheckIfUncommented( attr
, *mpGlobalVarsIdx
) )
528 mpGlobalVarsIdx
->AddSection( pSection
, TRUE
);
532 AddToCurrentClass( pSection
, attr
, "Attributes" );
535 void RipperDocGen::VisitOperation( spOperation
& op
)
539 AppendHighlightedSource( body
, op
.GetFullName(mTags
) );
541 AppendComments( op
, body
);
543 ScriptSection
* pSection
=
544 new ScriptSection( GetScopedName( op
), body
,
546 GetRefTemplFor( op
) );
548 if ( !op
.IsInClass() )
550 if ( CheckIfUncommented( op
, *mpGlobalFuncIdx
) )
553 mpGlobalFuncIdx
->AddSection( pSection
, 1 );
556 AddToCurrentClass( pSection
, op
, "Operations" );
559 bool RipperDocGen::OnSaveDocument( ScriptStream
& stm
)
561 LinkSuperClassRefs();
563 // FOR NOW:: doesn't work yet
564 //mpTopIdx->RemoveEmptySections();
566 return 1; // saving can proceed now