]> git.saurik.com Git - wxWidgets.git/blob - utils/HelpGen/src/srcparser.cpp
added wxGetTopLevelParent()
[wxWidgets.git] / utils / HelpGen / src / srcparser.cpp
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 #ifdef __GNUG__
13 # pragma implementation "srcparser.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #ifndef __DARWIN__
28 # include <malloc.h>
29 #endif
30 #include <stdio.h>
31
32 #include "srcparser.h"
33
34 /***** Implementation for class spVisitor *****/
35
36 void spVisitor::VisitAll( spContext& atContext,
37 bool sortContent
38 )
39 {
40 mSiblingSkipped = FALSE;
41 mChildSkipped = FALSE;
42 mContextMask = SP_CTX_ANY; // FIXME:: should be an arg.
43
44 if ( sortContent && !atContext.IsSorted() )
45
46 atContext.SortMembers();
47
48 mpCurCxt = &atContext; // FIXME:: this is dirty, restoring it each time
49
50 if ( atContext.GetContextType() & mContextMask )
51
52 atContext.AcceptVisitor( *this );
53
54 MMemberListT& members = atContext.GetMembers();
55
56 for( size_t i = 0; i != members.size(); ++i )
57 {
58 if ( mSiblingSkipped )
59
60 return;
61
62 if ( !mChildSkipped )
63 {
64 size_t prevSz = members.size();
65
66 // visit members of the context recursivelly
67 VisitAll( *members[i], sortContent );
68
69 if ( members.size() != prevSz )
70
71 --i; // current member was removed!
72
73 mChildSkipped = 0;
74 }
75 }
76 }
77
78 void spVisitor::RemoveCurrentContext()
79 {
80 if ( mpCurCxt->GetParent() )
81
82 mpCurCxt->GetParent()->RemoveChild( mpCurCxt );
83 }
84
85 void spVisitor::SkipSiblings()
86 {
87 mSiblingSkipped = TRUE;
88 }
89
90 void spVisitor::SkipChildren()
91 {
92 mChildSkipped = TRUE;
93 }
94
95 void spVisitor::SetFilter( int contextMask )
96 {
97 mContextMask = contextMask;
98 }
99
100 /***** Implementation for class spComment *****/
101
102 bool spComment::IsMultiline() const
103 {
104 return mIsMultiline;
105 }
106
107 bool spComment::StartsParagraph() const
108 {
109 return mStartsPar;
110 }
111
112 string& spComment::GetText()
113 {
114 return mText;
115 }
116
117 string spComment::GetText() const
118 {
119 return mText;
120 }
121
122 /***** Implementation for class spContext *****/
123
124 spContext::spContext()
125
126 : mpParent ( NULL ),
127 mpFirstOccurence( NULL ),
128 mAlreadySorted ( FALSE ),
129
130 mSrcLineNo (-1),
131 mSrcOffset (-1),
132 mContextLength(-1),
133 mLastScrLineNo(-1),
134
135 mHeaderLength (-1),
136 mFooterLength (-1),
137
138 mFirstCharPos (-1),
139 mLastCharPos (-1),
140
141 mVisibility( SP_VIS_PRIVATE ),
142
143 mIsVirtualContext ( FALSE ),
144 mVirtualContextHasChildren( FALSE ),
145
146 mpUserData( NULL )
147 {}
148
149 void spContext::RemoveChildren()
150 {
151 for( size_t i = 0; i != mMembers.size(); ++i )
152
153 delete mMembers[i];
154
155 mMembers.erase( mMembers.begin(), mMembers.end() );
156 }
157
158 spContext::~spContext()
159 {
160 RemoveChildren();
161
162 for( size_t i = 0; i != mComments.size(); ++i )
163
164 delete mComments[i];
165 }
166
167 bool spContext::IsSorted()
168 {
169 return mAlreadySorted;
170 }
171
172 void spContext::GetContextList( MMemberListT& lst, int contextMask )
173 {
174 for( size_t i = 0; i != mMembers.size(); ++i )
175 {
176 spContext& member = *mMembers[i];
177
178 if ( member.GetContextType() & contextMask )
179
180 lst.push_back( &member );
181
182 // collect required contexts recursively
183 member.GetContextList( lst, contextMask );
184 }
185 }
186
187 bool spContext::HasComments()
188 {
189 return ( mComments.size() != 0 );
190 }
191
192 void spContext::RemoveChild( spContext* pChild )
193 {
194 for( size_t i = 0; i != mMembers.size(); ++i )
195
196 if ( mMembers[i] == pChild )
197 {
198 mMembers.erase( &mMembers[i] );
199
200 delete pChild;
201 return;
202 }
203
204 // the given child should exist on the parent's list
205 wxASSERT( 0 );
206 }
207
208 spContext* spContext::GetEnclosingContext( int mask )
209 {
210 spContext* cur = this->GetParent();
211
212 while ( cur && !(cur->GetContextType() & mask) )
213
214 cur = cur->GetParent();
215
216 return cur;
217 }
218
219 bool spContext::PositionIsKnown()
220 {
221 return ( mSrcOffset != (-1) && mContextLength != (-1) );
222 }
223
224 bool spContext::IsVirtualContext()
225 {
226 return mIsVirtualContext;
227 }
228
229 bool spContext::VitualContextHasChildren()
230 {
231 return mVirtualContextHasChildren;
232 }
233
234 string spContext::GetVirtualContextBody()
235 {
236 wxASSERT( mIsVirtualContext );
237
238 return mVirtualContextBody;
239 }
240
241 string spContext::GetFooterOfVirtualContextBody()
242 {
243 wxASSERT( mIsVirtualContext );
244
245 return mVittualContextFooter;
246 }
247
248
249 void spContext::SetVirtualContextBody( const string& body,
250 bool hasChildren,
251 const string& footer )
252 {
253 mVirtualContextHasChildren = hasChildren;
254
255 mVirtualContextBody = body;
256 mVittualContextFooter = footer;
257
258 // atuomaticllay becomes virtual context
259
260 mIsVirtualContext = TRUE;
261 }
262
263 string spContext::GetBody( spContext* pCtx )
264 {
265 if ( ( pCtx == NULL || pCtx == this ) && mIsVirtualContext )
266
267 return mVirtualContextBody;
268
269 if ( GetParent() )
270
271 return GetParent()->GetBody( ( pCtx != NULL ) ? pCtx : this );
272 else
273 return ""; // source-fragment cannot be found
274 }
275
276 string spContext::GetHeader( spContext* pCtx )
277 {
278 if ( GetParent() )
279
280 return GetParent()->GetHeader( ( pCtx != NULL ) ? pCtx : this );
281 else
282 return ""; // source-fragment cannot be found
283 }
284
285 bool spContext::IsFirstOccurence()
286 {
287 return ( mpFirstOccurence != 0 );
288 }
289
290 spContext* spContext::GetFirstOccurence()
291 {
292 // this object should not itself be
293 // the first occurence of the context
294 wxASSERT( mpFirstOccurence != 0 );
295
296 return mpFirstOccurence;
297 }
298
299 void spContext::AddMember( spContext* pMember )
300 {
301 mMembers.push_back( pMember );
302
303 pMember->mpParent = this;
304 }
305
306 void spContext::AddComment( spComment* pComment )
307 {
308 mComments.push_back( pComment );
309 }
310
311 MMemberListT& spContext::GetMembers()
312 {
313 return mMembers;
314 }
315
316 spContext* spContext::FindContext( const string& identifier,
317 int contextType,
318 bool searchSubMembers
319 )
320 {
321 for( size_t i = 0; i != mMembers.size(); ++i )
322 {
323 spContext& member = *mMembers[i];
324
325 if ( member.GetName() == identifier &&
326 ( contextType & member.GetContextType() )
327 )
328
329 return &member;
330
331 if ( searchSubMembers )
332 {
333 spContext* result =
334 member.FindContext( identifier, contextType, 1 );
335
336 if ( result ) return result;
337 }
338 }
339
340 return 0;
341 }
342
343 void spContext::RemoveThisContext()
344 {
345 if ( mpParent )
346 mpParent->RemoveChild( this );
347 else
348 // context should have a parent
349 wxFAIL_MSG("Context should have a parent");
350 }
351
352 spContext* spContext::GetOutterContext()
353 {
354 return mpParent;
355 }
356
357 bool spContext::HasOutterContext()
358 {
359 return ( mpParent != 0 );
360 }
361
362 bool spContext::IsInFile()
363 {
364 return ( GetOutterContext()->GetContextType() == SP_CTX_FILE );
365 }
366
367 bool spContext::IsInNameSpace()
368 {
369 return ( GetOutterContext()->GetContextType() == SP_CTX_NAMESPACE );
370 }
371
372 bool spContext::IsInClass()
373 {
374 return ( GetOutterContext()->GetContextType() == SP_CTX_CLASS );
375 }
376
377 bool spContext::IsInOperation()
378 {
379 return ( GetOutterContext()->GetContextType() == SP_CTX_OPERATION );
380 }
381
382 spClass& spContext::GetClass()
383 {
384 wxASSERT( GetOutterContext()->GetType() == SP_CTX_CLASS );
385 return *((spClass*)mpParent );
386 }
387
388 spFile& spContext::GetFile()
389 {
390 wxASSERT( GetOutterContext()->GetType() == SP_CTX_FILE );
391 return *((spFile*)mpParent );
392 }
393
394 spNameSpace& spContext::GetNameSpace()
395 {
396 wxASSERT( GetOutterContext()->GetType() == SP_CTX_NAMESPACE );
397 return *((spNameSpace*)mpParent );
398 }
399
400 spOperation& spContext::GetOperation()
401 {
402 wxASSERT( GetOutterContext()->GetType() == SP_CTX_OPERATION );
403 return *((spOperation*)mpParent );
404 }
405
406 /***** Implementation for class spClass *****/
407
408 void spClass::SortMembers()
409 {
410 // TBD::
411 }
412
413 /***** Implementation for class spOperation *****/
414
415 spOperation::spOperation()
416
417 : mHasDefinition( FALSE )
418 {
419 mIsConstant =
420 mIsVirtual =
421 mHasDefinition = false;
422 }
423
424 string spOperation::GetFullName(MarkupTagsT tags)
425 {
426 string txt = tags[TAG_BOLD].start + mRetType;
427 txt += " ";
428 txt += mName;
429 txt += "( ";
430 txt += tags[TAG_BOLD].end;
431
432 for( size_t i = 0; i != mMembers.size(); ++i )
433 {
434 // DBG::
435 wxASSERT( mMembers[i]->GetContextType() == SP_CTX_PARAMETER );
436
437 spParameter& param = *((spParameter*)mMembers[i]);
438
439 if ( i != 0 )
440 txt += ", ";
441
442 txt += tags[TAG_BOLD].start;
443
444 txt += param.mType;
445
446 txt += tags[TAG_BOLD].end;
447 txt += tags[TAG_ITALIC].start;
448
449 txt += " ";
450 txt += param.mName;
451
452 if ( param.mInitVal != "" )
453 {
454 txt += " = ";
455 txt += tags[TAG_BOLD].start;
456
457 txt += param.mInitVal;
458
459 txt += tags[TAG_BOLD].end;
460 }
461
462 txt += tags[TAG_ITALIC].end;;
463 }
464
465 txt += tags[TAG_BOLD].start;
466 txt += " )";
467 txt += tags[TAG_BOLD].end;
468
469 // TBD:: constantness of method
470
471 return txt;
472 }
473
474 /***** Implemenentation for class spPreprocessorLine *****/
475
476 string spPreprocessorLine::CPP_GetIncludedFileNeme() const
477 {
478 wxASSERT( GetStatementType() == SP_PREP_DEF_INCLUDE_FILE );
479
480 size_t i = 0;
481
482 while( i < mLine.length() && mLine[i] != '"' && mLine[i] != '<' )
483
484 ++i;
485
486 ++i;
487
488 size_t start = i;
489
490 while( i < mLine.length() && mLine[i] != '"' && mLine[i] != '>' )
491
492 ++i;
493
494 if ( start < mLine.length() )
495 {
496 string fname;
497 fname.append( mLine, start, ( i - start ) );
498
499 return fname;
500 }
501 else
502 return ""; // syntax error probably
503 }
504
505
506
507 /***** Implemenentation for class SourceParserBase *****/
508
509 SourceParserBase::SourceParserBase()
510
511 : mpFileBuf( NULL ),
512 mFileBufSz( 0 ),
513
514 mpPlugin( NULL )
515 {}
516
517 SourceParserBase::~SourceParserBase()
518 {
519 if ( mpFileBuf ) free( mpFileBuf );
520
521 if ( mpPlugin ) delete mpPlugin;
522 }
523
524 spFile* SourceParserBase::ParseFile( const char* fname )
525 {
526 // FIXME:: the below should not be fixed!
527
528 const size_t MAX_BUF_SIZE = 1024*256;
529
530 if ( !mpFileBuf ) mpFileBuf = (char*)malloc( MAX_BUF_SIZE );
531
532 mFileBufSz = MAX_BUF_SIZE;
533
534 FILE* fp = fopen( fname, "rt" );
535
536 if ( (int)fp == -1 || !fp ) return NULL;
537
538 int sz = fread( mpFileBuf, 1, mFileBufSz, fp );
539
540 return Parse( mpFileBuf, mpFileBuf + sz );
541 }
542
543 void SourceParserBase::SetPlugin( SourceParserPlugin* pPlugin )
544 {
545 if ( mpPlugin ) delete mpPlugin;
546
547 mpPlugin = pPlugin;
548 }
549
550 // ===========================================================================
551 // debug methods
552 // ===========================================================================
553
554 #ifdef __WXDEBUG__
555
556 void spContext::Dump(const wxString& indent) const
557 {
558 DumpThis(indent);
559
560 // increase it for the children
561 wxString indentChild = indent + " ";
562
563 for ( MMemberListT::const_iterator i = mMembers.begin();
564 i != mMembers.end();
565 i++ ) {
566 (*i)->Dump(indentChild);
567 }
568 }
569
570 void spContext::DumpThis(const wxString& indent) const
571 {
572 wxFAIL_MSG("abstract base class can't be found in parser tree!");
573 }
574
575 void spParameter::DumpThis(const wxString& indent) const
576 {
577 wxLogDebug("%sparam named '%s' of type '%s'",
578 indent.c_str(), mName.c_str(), mType.c_str());
579 }
580
581 void spAttribute::DumpThis(const wxString& indent) const
582 {
583 wxLogDebug("%svariable named '%s' of type '%s'",
584 indent.c_str(), mName.c_str(), mType.c_str());
585 }
586
587 void spOperation::DumpThis(const wxString& indent) const
588 {
589 wxString protection;
590 if ( !!mScope ) {
591 switch ( mVisibility ) {
592 case SP_VIS_PUBLIC:
593 protection = "public";
594 break;
595
596 case SP_VIS_PROTECTED:
597 protection = "protected";
598 break;
599
600 case SP_VIS_PRIVATE:
601 protection = "private";
602 break;
603
604 default:
605 wxFAIL_MSG("unknown protection type");
606 }
607 }
608 else {
609 protection = "global";
610 }
611
612 wxLogDebug("%s%s%s%s function named '%s::%s' of type '%s'",
613 indent.c_str(),
614 mIsConstant ? "const " : "",
615 mIsVirtual ? "virtual " : "",
616 protection.c_str(),
617 mScope.c_str(), mName.c_str(), mRetType.c_str());
618 }
619
620 void spPreprocessorLine::DumpThis(const wxString& indent) const
621 {
622 wxString kind;
623 switch ( mDefType ) {
624 case SP_PREP_DEF_DEFINE_SYMBOL:
625 kind = "define";
626 break;
627
628 case SP_PREP_DEF_REDEFINE_SYMBOL:
629 kind = "redefine";
630 break;
631
632 case SP_PREP_DEF_INCLUDE_FILE:
633 kind.Printf("include (%s)", CPP_GetIncludedFileNeme().c_str());
634 break;
635
636 case SP_PREP_DEF_OTHER:
637 kind = "other";
638 break;
639
640 }
641
642 wxLogDebug("%spreprocessor statement: %s",
643 indent.c_str(), kind.c_str());
644 }
645
646 void spClass::DumpThis(const wxString& indent) const
647 {
648 wxString base;
649 for ( StrListT::const_iterator i = mSuperClassNames.begin();
650 i != mSuperClassNames.end();
651 i++ ) {
652 if ( !!base )
653 base += ", ";
654 base += *i;
655 }
656
657 if ( !base )
658 base = "none";
659
660 wxString kind;
661 switch ( mClassSubType ) {
662 case SP_CLTYPE_CLASS:
663 kind = "class";
664 break;
665
666 case SP_CLTYPE_TEMPLATE_CLASS:
667 kind = "template class";
668 break;
669
670 case SP_CLTYPE_STRUCTURE:
671 kind = "struc";
672 break;
673
674 case SP_CLTYPE_UNION:
675 kind = "union";
676 break;
677
678 case SP_CLTYPE_INTERFACE:
679 kind = "interface";
680 break;
681
682 default:
683 wxFAIL_MSG("unknown class subtype");
684 }
685
686 wxLogDebug("%s%s named '%s' (base classes: %s)",
687 indent.c_str(), kind.c_str(),
688 mName.c_str(), base.c_str());
689 }
690
691 void spEnumeration::DumpThis(const wxString& indent) const
692 {
693 wxLogDebug("%senum named '%s'",
694 indent.c_str(), mName.c_str());
695 }
696
697 void spTypeDef::DumpThis(const wxString& indent) const
698 {
699 wxLogDebug("%stypedef %s = %s",
700 indent.c_str(), mName.c_str(), mOriginalType.c_str());
701 }
702
703 void spFile::DumpThis(const wxString& indent) const
704 {
705 wxLogDebug("%sfile '%s'",
706 indent.c_str(), mFileName.c_str());
707 }
708
709 #endif // __WXDEBUG__