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