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