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