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