]>
Commit | Line | Data |
---|---|---|
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 += m_Name; | |
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.m_Name; | |
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 ( !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& WXUNUSED(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(), m_Name.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(), m_Name.c_str(), mType.c_str()); | |
585 | } | |
586 | ||
587 | void spOperation::DumpThis(const wxString& indent) const | |
588 | { | |
589 | wxString protection; | |
590 | if ( !mScope.empty() ) { | |
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(), m_Name.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.empty() ) | |
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 | m_Name.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(), m_Name.c_str()); | |
695 | } | |
696 | ||
697 | void spTypeDef::DumpThis(const wxString& indent) const | |
698 | { | |
699 | wxLogDebug("%stypedef %s = %s", | |
700 | indent.c_str(), m_Name.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__ |