]> git.saurik.com Git - wxWidgets.git/blob - utils/HelpGen/src/srcparser.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[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 // 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
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
71 void spVisitor::RemoveCurrentContext()
72 {
73 if ( mpCurCxt->GetParent() )
74
75 mpCurCxt->GetParent()->RemoveChild( mpCurCxt );
76 }
77
78 void spVisitor::SkipSiblings()
79 {
80 mSiblingSkipped = true;
81 }
82
83 void spVisitor::SkipChildren()
84 {
85 mChildSkipped = true;
86 }
87
88 void spVisitor::SetFilter( int contextMask )
89 {
90 mContextMask = contextMask;
91 }
92
93 /***** Implementation for class spComment *****/
94
95 bool spComment::IsMultiline() const
96 {
97 return mIsMultiline;
98 }
99
100 bool spComment::StartsParagraph() const
101 {
102 return mStartsPar;
103 }
104
105 wxString& spComment::GetText()
106 {
107 return m_Text;
108 }
109
110 wxString spComment::GetText() const
111 {
112 return m_Text;
113 }
114
115 /***** Implementation for class spContext *****/
116
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
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
151 spContext::~spContext()
152 {
153 RemoveChildren();
154
155 for( size_t i = 0; i != mComments.size(); ++i )
156
157 delete mComments[i];
158 }
159
160 bool spContext::IsSorted()
161 {
162 return mAlreadySorted;
163 }
164
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
180 bool spContext::HasComments()
181 {
182 return ( mComments.size() != 0 );
183 }
184
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
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
212 bool spContext::PositionIsKnown()
213 {
214 return ( mSrcOffset != (-1) && mContextLength != (-1) );
215 }
216
217 bool spContext::IsVirtualContext()
218 {
219 return mIsVirtualContext;
220 }
221
222 bool spContext::VitualContextHasChildren()
223 {
224 return mVirtualContextHasChildren;
225 }
226
227 wxString spContext::GetVirtualContextBody()
228 {
229 wxASSERT( mIsVirtualContext );
230
231 return mVirtualContextBody;
232 }
233
234 wxString spContext::GetFooterOfVirtualContextBody()
235 {
236 wxASSERT( mIsVirtualContext );
237
238 return mVittualContextFooter;
239 }
240
241
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
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
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
275 bool spContext::IsFirstOccurence()
276 {
277 return ( mpFirstOccurence != 0 );
278 }
279
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
289 void spContext::AddMember( spContext* pMember )
290 {
291 mMembers.push_back( pMember );
292
293 pMember->m_pParent = this;
294 }
295
296 void spContext::AddComment( spComment* pComment )
297 {
298 mComments.push_back( pComment );
299 }
300
301 MMemberListT& spContext::GetMembers()
302 {
303 return mMembers;
304 }
305
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
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
342 spContext* spContext::GetOutterContext()
343 {
344 return m_pParent;
345 }
346
347 bool spContext::HasOutterContext()
348 {
349 return ( m_pParent != 0 );
350 }
351
352 bool spContext::IsInFile()
353 {
354 return ( GetOutterContext()->GetContextType() == SP_CTX_FILE );
355 }
356
357 bool spContext::IsInNameSpace()
358 {
359 return ( GetOutterContext()->GetContextType() == SP_CTX_NAMESPACE );
360 }
361
362 bool spContext::IsInClass()
363 {
364 return ( GetOutterContext()->GetContextType() == SP_CTX_CLASS );
365 }
366
367 bool spContext::IsInOperation()
368 {
369 return ( GetOutterContext()->GetContextType() == SP_CTX_OPERATION );
370 }
371
372 spClass& spContext::GetClass()
373 {
374 wxASSERT( GetOutterContext()->GetType() == SP_CTX_CLASS );
375 return *((spClass*)m_pParent );
376 }
377
378 spFile& spContext::GetFile()
379 {
380 wxASSERT( GetOutterContext()->GetType() == SP_CTX_FILE );
381 return *((spFile*)m_pParent );
382 }
383
384 spNameSpace& spContext::GetNameSpace()
385 {
386 wxASSERT( GetOutterContext()->GetType() == SP_CTX_NAMESPACE );
387 return *((spNameSpace*)m_pParent );
388 }
389
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
398 void spClass::SortMembers()
399 {
400 // TBD::
401 }
402
403 /***** Implementation for class spOperation *****/
404
405 spOperation::spOperation()
406
407 : mHasDefinition( false )
408 {
409 mIsConstant =
410 mIsVirtual =
411 mHasDefinition = false;
412 }
413
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
466 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
499 SourceParserBase::SourceParserBase()
500
501 : mpFileBuf( NULL ),
502 mFileBufSz( 0 ),
503
504 mpPlugin( NULL )
505 {}
506
507 SourceParserBase::~SourceParserBase()
508 {
509 if ( mpFileBuf ) free( mpFileBuf );
510
511 if ( mpPlugin ) delete mpPlugin;
512 }
513
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
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
546 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
560 void spContext::DumpThis(const wxString& WXUNUSED(indent)) const
561 {
562 wxFAIL_MSG("abstract base class can't be found in parser tree!");
563 }
564
565 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
571 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
577 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
614 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
640 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
685 void spEnumeration::DumpThis(const wxString& indent) const
686 {
687 wxLogDebug("%senum named '%s'",
688 indent.c_str(), m_Name.c_str());
689 }
690
691 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
697 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__