]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: No names yet. | |
3 | // Purpose: Contrib. demo | |
4 | // Author: Aleksandras Gluchovas | |
5 | // Modified by: | |
6 | // Created: 22/09/98 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Aleskandars Gluchovas | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // For compilers that support precompilation, includes "wx/wx.h". | |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
16 | #pragma hdrstop | |
17 | #endif | |
18 | ||
19 | #ifndef WX_PRECOMP | |
20 | #include "wx/wx.h" | |
21 | #endif | |
22 | ||
23 | #include "docripper.h" | |
24 | ||
25 | #if wxUSE_IOSTREAMH | |
26 | #include <iostream.h> | |
27 | #else | |
28 | #include <iostream> | |
29 | #endif | |
30 | ||
31 | // script templates | |
32 | ||
33 | // ***** currently only HTML versions of variouse templates available ***** // | |
34 | ||
35 | static const char* HTM_TopTempl = | |
36 | ||
37 | "<html><body bgcolor=#FFFFFF>\n\ | |
38 | \n\n<!------ Automatically Generated by \"wxDocRipper\"------->\n\n\n\ | |
39 | <p><h2>$(NAME)</h2><p>\n\ | |
40 | <ul>\n\ | |
41 | $(REFLIST)\ | |
42 | </ul><p>\n\n\ | |
43 | "; | |
44 | ||
45 | static const char* HTM_ContentIdxTempl = | |
46 | ||
47 | "\ | |
48 | <a name=\"r$(ID)_$(NAME)\">\n\ | |
49 | <p><hr>\n\ | |
50 | <h2><p>$(NAME)<p></h2>\ | |
51 | <ul>\n\ | |
52 | $(REFLIST)\ | |
53 | </ul><p>\n\n\ | |
54 | "; | |
55 | ||
56 | static const char* HTM_SuperContentTempl = | |
57 | ||
58 | "\ | |
59 | <a name=\"r$(ID)_$(NAME)\">\n\ | |
60 | <p><hr>\n\ | |
61 | <p><h2>$(NAME)<p></h2>\ | |
62 | $(BODY)\n\ | |
63 | "; | |
64 | ||
65 | static const char* HTM_SubContentTempl = | |
66 | ||
67 | "\ | |
68 | <a name=\"r$(ID)_$(NAME)\">\n\ | |
69 | <p><hr>\n\ | |
70 | <p><h3>$(NAME)<p></h3>\ | |
71 | $(BODY)\n\ | |
72 | "; | |
73 | ||
74 | static const char* HTM_OutLineTempl = | |
75 | ||
76 | "\ | |
77 | <p>\n\ | |
78 | <b><font color=\"#FF0000\">$(NAME)</font></b><p>\n\ | |
79 | "; | |
80 | ||
81 | static const char* HTM_OutLine1Templ = | |
82 | ||
83 | "\ | |
84 | <p>\n\ | |
85 | <b><i><font color=\"#101010\">$(NAME)</font></i></b>\n\ | |
86 | <ul>\n\ | |
87 | $(REFLIST)\ | |
88 | </ul>\n\n\ | |
89 | "; | |
90 | ||
91 | static const char* HTM_RefTempl = | |
92 | ||
93 | "\ | |
94 | <li><a href=\"#r$(ID)_$(NAME)\">$(NAME)</A>\n\ | |
95 | "; | |
96 | ||
97 | static const char* HTM_DeadRefTempl = | |
98 | ||
99 | "\ | |
100 | <li></b>$(NAME)\n\ | |
101 | "; | |
102 | ||
103 | /***** Implementation for class RipperDocGen *****/ | |
104 | ||
105 | RipperDocGen::RipperDocGen() | |
106 | ||
107 | : mTopTempl ( HTM_TopTempl ), | |
108 | mContentIdxTempl ( HTM_ContentIdxTempl ), | |
109 | mSuperContentTempl( HTM_SuperContentTempl ), | |
110 | mSubContentTempl ( HTM_SubContentTempl ), | |
111 | mOutLineTempl ( HTM_OutLineTempl ), | |
112 | mOutLine1Templ ( HTM_OutLine1Templ ), | |
113 | ||
114 | mRefTempl ( HTM_RefTempl ), | |
115 | mDeadRefTempl ( HTM_DeadRefTempl ), | |
116 | ||
117 | mpCurClassSect(0) | |
118 | { | |
119 | // topIndex is not referenced | |
120 | mpTopIdx = new ScriptSection( "Source Code Contents" , wxEmptyString, &mTopTempl , 0 ); | |
121 | mpClassIdx = new ScriptSection( "Classes Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl ); | |
122 | mpEnumIdx = new ScriptSection( "Enumerations Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl ); | |
123 | mpTypeDefIdx = new ScriptSection( "Type Definitions Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl ); | |
124 | mpMacroIdx = new ScriptSection( "Macros Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl ); | |
125 | mpGlobalVarsIdx = new ScriptSection( "Global Variables Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl ); | |
126 | mpGlobalFuncIdx = new ScriptSection( "Global Functions Reference", wxEmptyString, &mContentIdxTempl, &mRefTempl ); | |
127 | mpConstIdx = new ScriptSection( "Constants Reference" , wxEmptyString, &mContentIdxTempl, &mRefTempl ); | |
128 | ||
129 | // assemble top index | |
130 | mpTopIdx->AddSection( mpClassIdx , 1 ); | |
131 | mpTopIdx->AddSection( mpEnumIdx , 1 ); | |
132 | mpTopIdx->AddSection( mpTypeDefIdx , 1 ); | |
133 | mpTopIdx->AddSection( mpMacroIdx , 1 ); | |
134 | mpTopIdx->AddSection( mpGlobalVarsIdx, 1 ); | |
135 | mpTopIdx->AddSection( mpGlobalFuncIdx, 1 ); | |
136 | mpTopIdx->AddSection( mpConstIdx , 1 ); | |
137 | ||
138 | // register reserved variables for index and description templates | |
139 | ScriptSection::RegisterTemplate( mTopTempl ); | |
140 | ScriptSection::RegisterTemplate( mContentIdxTempl ); | |
141 | ScriptSection::RegisterTemplate( mSuperContentTempl ); | |
142 | ScriptSection::RegisterTemplate( mSubContentTempl ); | |
143 | ScriptSection::RegisterTemplate( mOutLineTempl ); | |
144 | ScriptSection::RegisterTemplate( mOutLine1Templ ); | |
145 | ScriptSection::RegisterTemplate( mRefTempl ); | |
146 | ScriptSection::RegisterTemplate( mDeadRefTempl ); | |
147 | ||
148 | // create the top-most (interfile) context | |
149 | mpFileBinderCtx = new spFile(); | |
150 | ||
151 | // the default script is HTML | |
152 | m_Tags = get_HTML_markup_tags(); | |
153 | ||
154 | mpParser = 0; // no default parser! | |
155 | } | |
156 | ||
157 | void RipperDocGen::Init( SourceParserBase* pParser ) | |
158 | { | |
159 | mpParser = pParser; | |
160 | } | |
161 | ||
162 | RipperDocGen::~RipperDocGen() | |
163 | { | |
164 | delete mpFileBinderCtx; | |
165 | } | |
166 | ||
167 | void RipperDocGen::AppendComments( spContext& fromContext, wxString& str ) | |
168 | { | |
169 | if ( !fromContext.HasComments() ) return; | |
170 | ||
171 | size_t start = str.length(); | |
172 | ||
173 | str += m_Tags[TAG_BOLD].end; | |
174 | str += m_Tags[TAG_PARAGRAPH].start; | |
175 | ||
176 | MCommentListT& lst = fromContext.GetCommentList(); | |
177 | ||
178 | for( size_t i = 0; i != lst.size(); ++i ) | |
179 | { | |
180 | ||
181 | if ( i != 0 ) | |
182 | ||
183 | if ( lst[i]->StartsParagraph() ) | |
184 | { | |
185 | str += m_Tags[TAG_PARAGRAPH].start; | |
186 | } | |
187 | ||
188 | str += lst[i]->m_Text; | |
189 | } | |
190 | ||
191 | // remove new lines, and insert paragraph breaks | |
192 | ||
193 | // if empty lines found | |
194 | ||
195 | size_t len = str.length(); | |
196 | ||
197 | for( size_t n = start; n != len; ++n ) | |
198 | ||
199 | if ( str[n] == 10 || | |
200 | str[n] == 13 ) | |
201 | { | |
202 | if ( n + 2 < len ) | |
203 | { | |
204 | if ( ( str[n] == 13 && str[n+1] == 10 && // FIXME:: quick-hack | |
205 | str[n+2] == 13 ) || | |
206 | ( str[n] == 10 && str[n+1] == 10 ) | |
207 | ) | |
208 | { | |
209 | str.insert( n + 1, _T("<p>") ); // FIXME:: quick-hack | |
210 | len += 3; | |
211 | } | |
212 | } | |
213 | str[n] = _T(' '); | |
214 | } | |
215 | str += m_Tags[TAG_PARAGRAPH].end; | |
216 | } | |
217 | ||
218 | void RipperDocGen::AppendMulitilineStr( wxString& st, wxString& mlStr ) | |
219 | { | |
220 | st = m_Tags[TAG_FIXED_FONT].start; | |
221 | st += mlStr; | |
222 | st += m_Tags[TAG_FIXED_FONT].end; | |
223 | } | |
224 | ||
225 | void RipperDocGen::AppendHighlightedSource( wxString& st, wxString source ) | |
226 | { | |
227 | // FIXME:: below should not be fixed :) | |
228 | wxChar buf[1024*32]; | |
229 | ||
230 | // DBG::: | |
231 | // ASSERT( source.length() + 1 < sizeof(buf) ); | |
232 | ||
233 | wxStrcpy( buf, source.c_str() ); | |
234 | ||
235 | // highlight things | |
236 | mSrcPainter.Init(); | |
237 | mSrcPainter.ProcessSource( buf, strlen(buf) ); | |
238 | mSrcPainter.GetResultString( st, m_Tags ); | |
239 | } | |
240 | ||
241 | bool RipperDocGen::CheckIfUncommented( spContext& ctx, ScriptSection& toSect ) | |
242 | { | |
243 | if ( ctx.HasComments() ) return 0; | |
244 | ||
245 | toSect.AddReference( | |
246 | new ScriptSection( GetScopedName( ctx ), wxEmptyString, 0, &mDeadRefTempl ) | |
247 | ); | |
248 | ||
249 | return 1; | |
250 | } | |
251 | ||
252 | ScriptTemplate* RipperDocGen::GetRefTemplFor( spContext& ctx ) | |
253 | { | |
254 | if ( ctx.HasComments() ) | |
255 | return &mRefTempl; | |
256 | else | |
257 | return &mDeadRefTempl; | |
258 | } | |
259 | ||
260 | wxString RipperDocGen::GetScopedName( spContext& ofCtx ) | |
261 | { | |
262 | if ( ofCtx.IsInFile() ) | |
263 | return ofCtx.GetName(); | |
264 | else | |
265 | return ofCtx.GetOutterContext()->GetName() + | |
266 | _T("::") + ofCtx.GetName(); | |
267 | } | |
268 | ||
269 | void RipperDocGen::AddToCurrentClass( ScriptSection* pSection, spContext& ctx, | |
270 | const char* subSectionName ) | |
271 | { | |
272 | wxString sName; | |
273 | ||
274 | if ( ctx.mVisibility == SP_VIS_PROTECTED ) | |
275 | sName = "Protected members/"; | |
276 | else | |
277 | if ( ctx.mVisibility == SP_VIS_PRIVATE ) | |
278 | sName = "Private members/"; | |
279 | else | |
280 | sName = "Public members/"; | |
281 | ||
282 | sName += subSectionName; | |
283 | ||
284 | ScriptSection* pSect = mpCurClassSect->GetSubsection( sName.c_str() ); | |
285 | ||
286 | if ( CheckIfUncommented( ctx, *pSect ) ) | |
287 | { | |
288 | delete pSection; | |
289 | return; | |
290 | } | |
291 | ||
292 | pSect->AddReference( pSection ); | |
293 | ||
294 | mpCurClassSect->AddSection( pSection ); | |
295 | } | |
296 | ||
297 | void RipperDocGen::LinkSuperClassRefs() | |
298 | { | |
299 | MMemberListT clLst; | |
300 | ||
301 | // collect all classes in the context tree | |
302 | mpFileBinderCtx->GetContextList( clLst, SP_CTX_CLASS ); | |
303 | ||
304 | for( size_t i = 0; i != clLst.size(); ++i ) | |
305 | { | |
306 | spClass& cl = *((spClass*)clLst[i]); | |
307 | ||
308 | // FIXME:: why sometimes GetUserData() returns NULL? | |
309 | if ( !cl.GetUserData() ) | |
310 | continue; | |
311 | ||
312 | ScriptSection* pClSect = (ScriptSection*)cl.GetUserData(); | |
313 | ScriptSection* pSuperSect = pClSect->GetSubsection("Derived from"); | |
314 | ||
315 | for( size_t n = 0; n != cl.m_SuperClassNames.size(); ++n ) | |
316 | { | |
317 | wxString& superClName = cl.m_SuperClassNames[n]; | |
318 | ||
319 | spClass* pFound = NULL; | |
320 | ||
321 | for( size_t k = 0; k != clLst.size(); ++k ) | |
322 | { | |
323 | if ( clLst[k]->GetName() == superClName ) | |
324 | { | |
325 | pFound = (spClass*)clLst[k]; | |
326 | break; | |
327 | } | |
328 | } | |
329 | ||
330 | if ( !pFound ) | |
331 | { | |
332 | ScriptSection* pNotFound = | |
333 | new ScriptSection( superClName, wxEmptyString, 0, &mDeadRefTempl ); | |
334 | ||
335 | pSuperSect->AddReference( pNotFound ); | |
336 | } | |
337 | else | |
338 | if ( pFound->GetUserData() ) | |
339 | ||
340 | pSuperSect->AddReference( | |
341 | (ScriptSection*)pFound->GetUserData() ); | |
342 | } | |
343 | } | |
344 | } | |
345 | ||
346 | void RipperDocGen::ProcessFile( const char* sourceFile ) | |
347 | { | |
348 | wxSTD cout << "Processing file " << sourceFile << "..." << wxSTD endl; | |
349 | ||
350 | spFile* pCtx = mpParser->ParseFile( sourceFile ); | |
351 | ||
352 | if ( pCtx == NULL ) | |
353 | { | |
354 | wxSTD cout << "Cannot open file " << sourceFile << ", skipped..." << wxSTD endl; | |
355 | ||
356 | return; | |
357 | } | |
358 | ||
359 | VisitAll( *pCtx, true ); | |
360 | ||
361 | mpFileBinderCtx->AddMember( pCtx ); | |
362 | } | |
363 | ||
364 | // implementations of "visiting procedures" | |
365 | ||
366 | void RipperDocGen::VisitEnumeration( spEnumeration& en ) | |
367 | { | |
368 | // FOR NOW:: do not reference "nameless" enums | |
369 | if ( en.GetName().empty() ) return; | |
370 | ||
371 | if ( CheckIfUncommented( en, *mpEnumIdx ) ) | |
372 | return; | |
373 | ||
374 | wxString body; | |
375 | body += m_Tags[TAG_BOLD].start; | |
376 | ||
377 | AppendMulitilineStr( body, en.m_EnumContent ); | |
378 | ||
379 | body += m_Tags[TAG_BOLD].end; | |
380 | ||
381 | wxString line; | |
382 | AppendHighlightedSource( line, body ); | |
383 | AppendComments( en, line ); | |
384 | ||
385 | mpEnumIdx->AddSection( | |
386 | new ScriptSection( en.GetName(), line, | |
387 | &mSubContentTempl, | |
388 | GetRefTemplFor( en ) ), 1 | |
389 | ); | |
390 | } | |
391 | ||
392 | void RipperDocGen::VisitTypeDef( spTypeDef& td ) | |
393 | { | |
394 | if ( CheckIfUncommented( td, *mpTypeDefIdx ) ) | |
395 | return; | |
396 | ||
397 | wxString body; | |
398 | body += m_Tags[TAG_BOLD].start; | |
399 | body += "typdef "; | |
400 | body += m_Tags[TAG_BOLD].end; | |
401 | ||
402 | AppendMulitilineStr( body, td.m_OriginalType ); | |
403 | body += td.m_OriginalType; | |
404 | body += ' '; | |
405 | ||
406 | body += m_Tags[TAG_BOLD].start; | |
407 | body += td.GetName(); | |
408 | body += m_Tags[TAG_BOLD].end; | |
409 | ||
410 | wxString line; | |
411 | AppendHighlightedSource( line, body ); | |
412 | AppendComments( td, line ); | |
413 | ||
414 | mpTypeDefIdx->AddSection( | |
415 | new ScriptSection( td.GetName(), line, | |
416 | &mSubContentTempl, | |
417 | GetRefTemplFor( td ) ), true | |
418 | ); | |
419 | } | |
420 | ||
421 | void RipperDocGen::VisitPreprocessorLine( spPreprocessorLine& pd ) | |
422 | { | |
423 | if ( pd.mDefType != SP_PREP_DEF_REDEFINE_SYMBOL ) | |
424 | return; | |
425 | ||
426 | if ( CheckIfUncommented( pd, *mpMacroIdx ) ) | |
427 | return; | |
428 | ||
429 | wxString body; | |
430 | body += m_Tags[TAG_FIXED_FONT].start; | |
431 | ||
432 | wxString coloredLine = pd.m_Line; | |
433 | AppendHighlightedSource( coloredLine, pd.m_Line ); | |
434 | ||
435 | AppendMulitilineStr( body, coloredLine ); | |
436 | ||
437 | body += m_Tags[TAG_FIXED_FONT].end; | |
438 | ||
439 | AppendComments( pd, body ); | |
440 | ||
441 | mpMacroIdx->AddSection( | |
442 | new ScriptSection( pd.GetName(), body, | |
443 | &mSubContentTempl, | |
444 | GetRefTemplFor( pd ) ), true | |
445 | ); | |
446 | } | |
447 | ||
448 | void RipperDocGen::VisitClass( spClass& cl ) | |
449 | { | |
450 | // FOR NOW:: do not document nested classes - | |
451 | // nicier visiting method yet needed | |
452 | ||
453 | if ( cl.IsInClass() ) | |
454 | { | |
455 | SkipChildren(); // spVisitor's method | |
456 | return; | |
457 | } | |
458 | ||
459 | wxString body; | |
460 | AppendComments( cl, body ); | |
461 | ||
462 | mpCurClassSect = | |
463 | new ScriptSection( cl.GetName(), body, &mSuperContentTempl, &mRefTempl ); | |
464 | ||
465 | // set up reference in the class context, pointing back | |
466 | // to the section where this class is represented | |
467 | cl.SetUserData( mpCurClassSect ); | |
468 | ||
469 | ScriptSection* pSuper = new ScriptSection( "Derived from" ,wxEmptyString, &mOutLine1Templ,0, 1 ); | |
470 | ||
471 | ScriptSection* pPublic = new ScriptSection( "Public members" ,wxEmptyString, &mOutLineTempl,0, 1 ); | |
472 | ScriptSection* pProtected = new ScriptSection( "Protected members" ,wxEmptyString, &mOutLineTempl,0, 1 ); | |
473 | ScriptSection* pPrivate = new ScriptSection( "Private members" ,wxEmptyString, &mOutLineTempl,0, 1 ); | |
474 | ||
475 | pPublic->AddSection( new ScriptSection( "Operations", wxEmptyString, &mOutLine1Templ, 0, 1 ) ); | |
476 | pPublic->AddSection( new ScriptSection( "Attributes", wxEmptyString, &mOutLine1Templ, 0, 1 ) ); | |
477 | ||
478 | pProtected->AddSection( new ScriptSection( "Operations", wxEmptyString, &mOutLine1Templ, 0, 1 ) ); | |
479 | pProtected->AddSection( new ScriptSection( "Attributes", wxEmptyString, &mOutLine1Templ, 0, 1 ) ); | |
480 | ||
481 | pPrivate->AddSection( new ScriptSection( "Operations", wxEmptyString, &mOutLine1Templ, 0, 1 ) ); | |
482 | pPrivate->AddSection( new ScriptSection( "Attributes", wxEmptyString, &mOutLine1Templ, 0, 1 ) ); | |
483 | ||
484 | mpCurClassSect->AddSection( pSuper ); | |
485 | mpCurClassSect->AddSection( pPublic ); | |
486 | mpCurClassSect->AddSection( pProtected ); | |
487 | mpCurClassSect->AddSection( pPrivate ); | |
488 | ||
489 | mpClassIdx->AddSection( mpCurClassSect, true ); | |
490 | } | |
491 | ||
492 | void RipperDocGen::VisitAttribute( spAttribute& attr ) | |
493 | { | |
494 | wxString body; | |
495 | body += m_Tags[TAG_BOLD].start; | |
496 | body += attr.m_Type; | |
497 | body += m_Tags[TAG_BOLD].end; | |
498 | ||
499 | body += m_Tags[TAG_ITALIC].start; | |
500 | body += ' '; | |
501 | body += attr.GetName(); | |
502 | body += m_Tags[TAG_ITALIC].end; | |
503 | ||
504 | wxString line; | |
505 | AppendHighlightedSource( line, body ); | |
506 | AppendComments( attr, line ); | |
507 | ||
508 | ScriptSection* pSection = | |
509 | new ScriptSection( GetScopedName( attr ), line, | |
510 | &mSubContentTempl, | |
511 | GetRefTemplFor( attr ) ); | |
512 | ||
513 | if ( attr.mIsConstant ) | |
514 | mpConstIdx->AddSection( pSection, true ); | |
515 | else | |
516 | if ( !attr.IsInClass() ) | |
517 | { | |
518 | if ( CheckIfUncommented( attr, *mpGlobalVarsIdx ) ) | |
519 | return; | |
520 | mpGlobalVarsIdx->AddSection( pSection, true ); | |
521 | } | |
522 | else | |
523 | AddToCurrentClass( pSection, attr, "Attributes" ); | |
524 | } | |
525 | ||
526 | void RipperDocGen::VisitOperation( spOperation& op ) | |
527 | { | |
528 | wxString body; | |
529 | ||
530 | AppendHighlightedSource( body, op.GetFullName(m_Tags) ); | |
531 | ||
532 | AppendComments( op, body ); | |
533 | ||
534 | ScriptSection* pSection = | |
535 | new ScriptSection( GetScopedName( op ), body, | |
536 | &mSubContentTempl, | |
537 | GetRefTemplFor( op ) ); | |
538 | ||
539 | if ( !op.IsInClass() ) | |
540 | { | |
541 | if ( CheckIfUncommented( op, *mpGlobalFuncIdx ) ) | |
542 | return; | |
543 | ||
544 | mpGlobalFuncIdx->AddSection( pSection, 1 ); | |
545 | } | |
546 | else | |
547 | AddToCurrentClass( pSection, op, "Operations" ); | |
548 | } | |
549 | ||
550 | bool RipperDocGen::OnSaveDocument( ScriptStream& WXUNUSED(stm) ) | |
551 | { | |
552 | LinkSuperClassRefs(); | |
553 | ||
554 | // FOR NOW:: doesn't work yet | |
555 | //mpTopIdx->RemoveEmptySections(); | |
556 | ||
557 | return 1; // saving can proceed now | |
558 | } | |
559 |