]> git.saurik.com Git - wxWidgets.git/blob - utils/HelpGen/src/srcparser.cpp
3b0f1c922d19f9039226b8bc6b3f337ad173dc4b
[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 wxString& spComment::GetText()
113 {
114 return m_Text;
115 }
116
117 wxString spComment::GetText() const
118 {
119 return m_Text;
120 }
121
122 /***** Implementation for class spContext *****/
123
124 spContext::spContext()
125
126 : m_pParent ( 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 wxString spContext::GetVirtualContextBody()
235 {
236 wxASSERT( mIsVirtualContext );
237
238 return mVirtualContextBody;
239 }
240
241 wxString spContext::GetFooterOfVirtualContextBody()
242 {
243 wxASSERT( mIsVirtualContext );
244
245 return mVittualContextFooter;
246 }
247
248
249 void spContext::SetVirtualContextBody( const wxString& body,
250 bool hasChildren,
251 const wxString& 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 wxString spContext::GetBody( spContext* pCtx )
264 {
265 if ( ( pCtx == NULL || pCtx == this ) && mIsVirtualContext )
266 return mVirtualContextBody;
267
268 if ( GetParent() )
269 return GetParent()->GetBody( ( pCtx != NULL ) ? pCtx : this );
270 else
271 return wxEmptyString; // source-fragment cannot be found
272 }
273
274 wxString spContext::GetHeader( spContext* pCtx )
275 {
276 if ( GetParent() )
277 return GetParent()->GetHeader( ( pCtx != NULL ) ? pCtx : this );
278 else
279 return wxEmptyString; // source-fragment cannot be found
280 }
281
282 bool spContext::IsFirstOccurence()
283 {
284 return ( mpFirstOccurence != 0 );
285 }
286
287 spContext* spContext::GetFirstOccurence()
288 {
289 // this object should not itself be
290 // the first occurence of the context
291 wxASSERT( mpFirstOccurence != 0 );
292
293 return mpFirstOccurence;
294 }
295
296 void spContext::AddMember( spContext* pMember )
297 {
298 mMembers.push_back( pMember );
299
300 pMember->m_pParent = this;
301 }
302
303 void spContext::AddComment( spComment* pComment )
304 {
305 mComments.push_back( pComment );
306 }
307
308 MMemberListT& spContext::GetMembers()
309 {
310 return mMembers;
311 }
312
313 spContext* spContext::FindContext( const wxString& identifier,
314 int contextType,
315 bool searchSubMembers
316 )
317 {
318 for( size_t i = 0; i != mMembers.size(); ++i )
319 {
320 spContext& member = *mMembers[i];
321
322 if ( member.GetName() == identifier &&
323 ( contextType & member.GetContextType() )
324 )
325
326 return &member;
327
328 if ( searchSubMembers )
329 {
330 spContext* result =
331 member.FindContext( identifier, contextType, 1 );
332
333 if ( result ) return result;
334 }
335 }
336
337 return 0;
338 }
339
340 void spContext::RemoveThisContext()
341 {
342 if ( m_pParent )
343 m_pParent->RemoveChild( this );
344 else
345 // context should have a parent
346 wxFAIL_MSG("Context should have a parent");
347 }
348
349 spContext* spContext::GetOutterContext()
350 {
351 return m_pParent;
352 }
353
354 bool spContext::HasOutterContext()
355 {
356 return ( m_pParent != 0 );
357 }
358
359 bool spContext::IsInFile()
360 {
361 return ( GetOutterContext()->GetContextType() == SP_CTX_FILE );
362 }
363
364 bool spContext::IsInNameSpace()
365 {
366 return ( GetOutterContext()->GetContextType() == SP_CTX_NAMESPACE );
367 }
368
369 bool spContext::IsInClass()
370 {
371 return ( GetOutterContext()->GetContextType() == SP_CTX_CLASS );
372 }
373
374 bool spContext::IsInOperation()
375 {
376 return ( GetOutterContext()->GetContextType() == SP_CTX_OPERATION );
377 }
378
379 spClass& spContext::GetClass()
380 {
381 wxASSERT( GetOutterContext()->GetType() == SP_CTX_CLASS );
382 return *((spClass*)m_pParent );
383 }
384
385 spFile& spContext::GetFile()
386 {
387 wxASSERT( GetOutterContext()->GetType() == SP_CTX_FILE );
388 return *((spFile*)m_pParent );
389 }
390
391 spNameSpace& spContext::GetNameSpace()
392 {
393 wxASSERT( GetOutterContext()->GetType() == SP_CTX_NAMESPACE );
394 return *((spNameSpace*)m_pParent );
395 }
396
397 spOperation& spContext::GetOperation()
398 {
399 wxASSERT( GetOutterContext()->GetType() == SP_CTX_OPERATION );
400 return *((spOperation*)m_pParent );
401 }
402
403 /***** Implementation for class spClass *****/
404
405 void spClass::SortMembers()
406 {
407 // TBD::
408 }
409
410 /***** Implementation for class spOperation *****/
411
412 spOperation::spOperation()
413
414 : mHasDefinition( false )
415 {
416 mIsConstant =
417 mIsVirtual =
418 mHasDefinition = false;
419 }
420
421 wxString spOperation::GetFullName(MarkupTagsT tags)
422 {
423 wxString txt = tags[TAG_BOLD].start + m_RetType;
424 txt += _T(" ");
425 txt += m_Name;
426 txt += _T("( ");
427 txt += tags[TAG_BOLD].end;
428
429 for( size_t i = 0; i != mMembers.size(); ++i )
430 {
431 // DBG::
432 wxASSERT( mMembers[i]->GetContextType() == SP_CTX_PARAMETER );
433
434 spParameter& param = *((spParameter*)mMembers[i]);
435
436 if ( i != 0 )
437 txt += _T(", ");
438
439 txt += tags[TAG_BOLD].start;
440
441 txt += param.m_Type;
442
443 txt += tags[TAG_BOLD].end;
444 txt += tags[TAG_ITALIC].start;
445
446 txt += _T(" ");
447 txt += param.m_Name;
448
449 if ( !param.m_InitVal.empty() )
450 {
451 txt += _T(" = ");
452 txt += tags[TAG_BOLD].start;
453
454 txt += param.m_InitVal;
455
456 txt += tags[TAG_BOLD].end;
457 }
458
459 txt += tags[TAG_ITALIC].end;;
460 }
461
462 txt += tags[TAG_BOLD].start;
463 txt += " )";
464 txt += tags[TAG_BOLD].end;
465
466 // TBD:: constantness of method
467
468 return txt;
469 }
470
471 /***** Implemenentation for class spPreprocessorLine *****/
472
473 wxString spPreprocessorLine::CPP_GetIncludedFileNeme() const
474 {
475 wxASSERT( GetStatementType() == SP_PREP_DEF_INCLUDE_FILE );
476
477 size_t i = 0;
478
479 while( i < m_Line.length() && m_Line[i] != _T('"') && m_Line[i] != _T('<') )
480
481 ++i;
482
483 ++i;
484
485 size_t start = i;
486
487 while( i < m_Line.length() && m_Line[i] != _T('"') && m_Line[i] != _T('>') )
488
489 ++i;
490
491 if ( start < m_Line.length() )
492 {
493 wxString fname;
494 fname.append( m_Line, start, ( i - start ) );
495
496 return fname;
497 }
498 else
499 return wxEmptyString; // syntax error probably
500 }
501
502
503
504 /***** Implemenentation for class SourceParserBase *****/
505
506 SourceParserBase::SourceParserBase()
507
508 : mpFileBuf( NULL ),
509 mFileBufSz( 0 ),
510
511 mpPlugin( NULL )
512 {}
513
514 SourceParserBase::~SourceParserBase()
515 {
516 if ( mpFileBuf ) free( mpFileBuf );
517
518 if ( mpPlugin ) delete mpPlugin;
519 }
520
521 spFile* SourceParserBase::ParseFile( const char* fname )
522 {
523 // FIXME:: the below should not be fixed!
524
525 const size_t MAX_BUF_SIZE = 1024*256;
526
527 if ( !mpFileBuf ) mpFileBuf = (char*)malloc( MAX_BUF_SIZE );
528
529 mFileBufSz = MAX_BUF_SIZE;
530
531 FILE* fp = fopen( fname, "rt" );
532
533 if ( !fp ) return NULL;
534
535 int sz = fread( mpFileBuf, 1, mFileBufSz, fp );
536
537 return Parse( mpFileBuf, mpFileBuf + sz );
538 }
539
540 void SourceParserBase::SetPlugin( SourceParserPlugin* pPlugin )
541 {
542 if ( mpPlugin ) delete mpPlugin;
543
544 mpPlugin = pPlugin;
545 }
546
547 // ===========================================================================
548 // debug methods
549 // ===========================================================================
550
551 #ifdef __WXDEBUG__
552
553 void spContext::Dump(const wxString& indent) const
554 {
555 DumpThis(indent);
556
557 // increase it for the children
558 wxString indentChild = indent + " ";
559
560 for ( MMemberListT::const_iterator i = mMembers.begin();
561 i != mMembers.end();
562 i++ ) {
563 (*i)->Dump(indentChild);
564 }
565 }
566
567 void spContext::DumpThis(const wxString& WXUNUSED(indent)) const
568 {
569 wxFAIL_MSG("abstract base class can't be found in parser tree!");
570 }
571
572 void spParameter::DumpThis(const wxString& indent) const
573 {
574 wxLogDebug("%sparam named '%s' of type '%s'",
575 indent.c_str(), m_Name.c_str(), m_Type.c_str());
576 }
577
578 void spAttribute::DumpThis(const wxString& indent) const
579 {
580 wxLogDebug("%svariable named '%s' of type '%s'",
581 indent.c_str(), m_Name.c_str(), m_Type.c_str());
582 }
583
584 void spOperation::DumpThis(const wxString& indent) const
585 {
586 wxString protection;
587 if ( !mScope.empty() ) {
588 switch ( mVisibility ) {
589 case SP_VIS_PUBLIC:
590 protection = "public";
591 break;
592
593 case SP_VIS_PROTECTED:
594 protection = "protected";
595 break;
596
597 case SP_VIS_PRIVATE:
598 protection = "private";
599 break;
600
601 default:
602 wxFAIL_MSG("unknown protection type");
603 }
604 }
605 else {
606 protection = "global";
607 }
608
609 wxString constStr,virtualStr;
610 if(mIsConstant) constStr = _T("const ");
611 if(mIsVirtual) virtualStr = _T("virtual ");
612
613 wxLogDebug("%s%s%s%s function named '%s::%s' of type '%s'",
614 indent.c_str(),
615 constStr.c_str(),
616 virtualStr.c_str(),
617 protection.c_str(),
618 mScope.c_str(), m_Name.c_str(), m_RetType.c_str());
619 }
620
621 void spPreprocessorLine::DumpThis(const wxString& indent) const
622 {
623 wxString kind;
624 switch ( mDefType ) {
625 case SP_PREP_DEF_DEFINE_SYMBOL:
626 kind = "define";
627 break;
628
629 case SP_PREP_DEF_REDEFINE_SYMBOL:
630 kind = "redefine";
631 break;
632
633 case SP_PREP_DEF_INCLUDE_FILE:
634 kind.Printf("include (%s)", CPP_GetIncludedFileNeme().c_str());
635 break;
636
637 case SP_PREP_DEF_OTHER:
638 kind = "other";
639 break;
640
641 }
642
643 wxLogDebug("%spreprocessor statement: %s",
644 indent.c_str(), kind.c_str());
645 }
646
647 void spClass::DumpThis(const wxString& indent) const
648 {
649 wxString base;
650 for ( StrListT::const_iterator i = m_SuperClassNames.begin();
651 i != m_SuperClassNames.end();
652 i++ ) {
653 if ( !base.empty() )
654 base += ", ";
655 base += *i;
656 }
657
658 if ( !base )
659 base = "none";
660
661 wxString kind;
662 switch ( mClassSubType ) {
663 case SP_CLTYPE_CLASS:
664 kind = "class";
665 break;
666
667 case SP_CLTYPE_TEMPLATE_CLASS:
668 kind = "template class";
669 break;
670
671 case SP_CLTYPE_STRUCTURE:
672 kind = "struc";
673 break;
674
675 case SP_CLTYPE_UNION:
676 kind = "union";
677 break;
678
679 case SP_CLTYPE_INTERFACE:
680 kind = "interface";
681 break;
682
683 default:
684 wxFAIL_MSG("unknown class subtype");
685 }
686
687 wxLogDebug("%s%s named '%s' (base classes: %s)",
688 indent.c_str(), kind.c_str(),
689 m_Name.c_str(), base.c_str());
690 }
691
692 void spEnumeration::DumpThis(const wxString& indent) const
693 {
694 wxLogDebug("%senum named '%s'",
695 indent.c_str(), m_Name.c_str());
696 }
697
698 void spTypeDef::DumpThis(const wxString& indent) const
699 {
700 wxLogDebug("%stypedef %s = %s",
701 indent.c_str(), m_Name.c_str(), m_OriginalType.c_str());
702 }
703
704 void spFile::DumpThis(const wxString& indent) const
705 {
706 wxLogDebug("%sfile '%s'",
707 indent.c_str(), m_FileName.c_str());
708 }
709
710 #endif // __WXDEBUG__