]> git.saurik.com Git - wxWidgets.git/blame - utils/HelpGen/src/cjparser.cpp
No default args in headers for SetSizeHints minimal size. Fixed docs.
[wxWidgets.git] / utils / HelpGen / src / cjparser.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
8ad74db3 9// Licence: wxWindows licence
cecfc5e7
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
ad053960 13# pragma implementation "acell.h"
cecfc5e7
VZ
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#include "cjparser.h"
28
29#if defined( wxUSE_TEMPLATE_STL )
30
d12e3536 31 #include <map>
cecfc5e7
VZ
32
33#else
34
d12e3536 35 #include "wxstlac.h"
cecfc5e7
VZ
36
37#endif
38
39
40/***** Implementation for class SJParser *****/
41
42// statics used by inline'ed C helper-functions
43static char* _gSrcStart = 0;
44static char* _gSrcEnd = 0;
e48f6880 45static wxChar* _gLastSuppresedComment = 0;
cecfc5e7
VZ
46static int _gLineNo = 0;
47
48// FOR NOW:: comments queue is static
49#define MAX_CQ_ENTRIES 128
50static char* _gCommentsQueue[MAX_CQ_ENTRIES];
51static int _gCQSize = 0;
52
53/***** keyword map related structures *****/
54
d12e3536 55struct less_c_str
cecfc5e7 56{
d12e3536
VZ
57 inline bool operator()( char* x, char* y) const
58 { return ( strcmp( x,y ) < 0 );
59 }
cecfc5e7
VZ
60};
61
62//WXSTL_MAP(CharPtrT,CharPtrT, LESS_THEN_FUNCTOR(CharPtrT));
63
64#if defined( wxUSE_TEMPLATE_STL )
65
d12e3536 66 typedef map< char*, char*, less_c_str > KeywordMapT;
cecfc5e7
VZ
67
68#else
69
d12e3536
VZ
70 typedef char* CharPtrT;
71 typedef WXSTL_MAP( CharPtrT, CharPtrT ,less_c_str) KeywordMapT;
cecfc5e7
VZ
72
73#endif
74
75static KeywordMapT __gMultiLangMap;
76static int __gMapReady = 0;
77
78static char* __gKeyWords[] =
79{
d12e3536
VZ
80 "public",
81 "protected",
82 "private",
83
84 "class",
85 "struct",
86 "union",
87 "enum",
88 "interface",
89
90 "package",
91 "import",
92
93 "typedef",
94 "template",
95 "friend",
96 "const",
97 "volatile",
98 "mutable",
99 "virtual",
100 "inline",
101 "static",
102 "register",
103
104 "final",
105 "abstract",
106 "native",
107
108 "__stdcall",
109 "extern",
110
111 0
cecfc5e7
VZ
112};
113
114static void check_keyword_map()
115{
d12e3536
VZ
116 if ( !__gMapReady )
117 {
118 __gMapReady = 1;
cecfc5e7 119
d12e3536
VZ
120 // "make sure" the address of the first member of non-polimorphic class
121 // coinsides with the address of the instance
cecfc5e7 122
d12e3536 123 char** keyword = __gKeyWords;
cecfc5e7 124
d12e3536
VZ
125 while ( (*keyword) != 0 )
126 {
127 __gMultiLangMap.insert(
128 KeywordMapT::value_type( *keyword, *keyword )
129 );
cecfc5e7 130
d12e3536
VZ
131 ++keyword;
132 }
133 }
cecfc5e7
VZ
134}
135
136/***** helper functions *****/
137
138static inline void skip_to_eol( char*& cur )
139{
d12e3536 140 while( *(cur) != 10 && *cur != 13 && cur < _gSrcEnd) ++cur;
cecfc5e7
VZ
141}
142
143static inline void skip_eol( char*& cur )
144{
d12e3536 145 if ( *cur == 13 )
cecfc5e7 146
d12e3536
VZ
147 cur += 2;
148 else
149 cur += 1;
cecfc5e7 150
d12e3536 151 ++_gLineNo;
cecfc5e7
VZ
152}
153
154static inline bool skip_to_next_comment_in_the_line( char*& cur )
155{
d12e3536
VZ
156 do
157 {
158 while( cur < _gSrcEnd &&
159 *cur != 10 &&
160 *cur != 13 &&
161 *cur != '/'
162 ) ++cur;
163
8ad74db3 164 if ( cur == _gSrcEnd ) return false;
d12e3536
VZ
165
166 if ( *cur == '/' )
167 {
168 if ( (*(cur+1) == '*') ||
8ad74db3 169 (*(cur+1) == '/') ) return true;
d12e3536
VZ
170 else
171 {
172 ++cur;
173 continue;
174 }
175 }
176
8ad74db3 177 return false;
d12e3536
VZ
178
179 } while(1);
cecfc5e7
VZ
180}
181
182inline static void store_line_no( int& toVar )
183{
d12e3536 184 toVar = _gLineNo;
cecfc5e7
VZ
185}
186
187inline static void restore_line_no( int storedLineNo )
188{
d12e3536 189 _gLineNo = storedLineNo;
cecfc5e7
VZ
190}
191
192inline static int get_line_no()
193{
d12e3536 194 return _gLineNo;
cecfc5e7
VZ
195}
196
197static void skip_to_prev_line( char*& cur )
198{
d12e3536
VZ
199 while( cur >= _gSrcStart &&
200 *cur != 10 &&
201 *cur != 13
202 ) --cur;
cecfc5e7 203
d12e3536
VZ
204 // NOTE:: '\n' is 13,10 for DOS
205 // '\n' is 10 for UNIX
cecfc5e7 206
d12e3536
VZ
207 // NOTE1: '\n' symbol is not used here,
208 // to provide possibility of loading
209 // file as binary
cecfc5e7 210
d12e3536
VZ
211 --cur;
212 if ( *cur == 10 )
213 {
214 ++cur;
215 return;
216 }
cecfc5e7 217
d12e3536 218 if ( *cur == 13 ) --cur;
cecfc5e7 219
d12e3536
VZ
220 while( cur >= _gSrcStart &&
221 *cur != 10 &&
222 *cur != 13
223 ) --cur;
cecfc5e7 224
d12e3536 225 ++cur; // move to the first character in the line
cecfc5e7
VZ
226}
227
228static inline void skip_comments( char*& cur )
229{
d12e3536 230 ++cur; // skip '/' token
cecfc5e7 231
d12e3536 232 if ( *cur != '/' && *cur != '*' ) return;
cecfc5e7 233
d12e3536
VZ
234 // first, store position of the comment into the queue
235 // (which further will be attached to the next context
236 // found)
cecfc5e7 237
d12e3536
VZ
238 if ( cur-1 != _gLastSuppresedComment )
239 {
240 if ( _gCQSize == MAX_CQ_ENTRIES )
241 {
242 size_t i = MAX_CQ_ENTRIES-1;
cecfc5e7 243
d12e3536
VZ
244 while( i != 0 )
245 {
246 _gCommentsQueue[i-1] = _gCommentsQueue[i];
247 --i;
248 }
cecfc5e7 249
d12e3536
VZ
250 --_gCQSize ;
251 }
cecfc5e7 252
d12e3536
VZ
253 _gCommentsQueue[_gCQSize++] = cur-1;
254 }
cecfc5e7 255
d12e3536
VZ
256 // if signle-line comment, skip it now
257 if ( *cur == '/' )
258 {
259 skip_to_eol( cur );
260 skip_eol( cur );
261 return;
262 }
cecfc5e7 263
d12e3536 264 size_t level = 1;
cecfc5e7 265
d12e3536 266 // check for multiline comment (handle nested multiline comments!)
cecfc5e7 267
d12e3536 268 int line_len = 0;
cecfc5e7 269
d12e3536
VZ
270 ++cur;
271 ++cur;
272 do
273 {
274 // TBD:: check eof cond.
cecfc5e7 275
d12e3536 276 // detect and remove vertical columns of '*''s
cecfc5e7 277
d12e3536
VZ
278 while ( *cur != '/' && cur < _gSrcEnd )
279 {
280 switch (*cur)
281 {
282 case '*' :
283 {
284 if ( *(cur+1) != '/' )
285 {
286 if ( line_len == 1 )
cecfc5e7 287
d12e3536
VZ
288 *cur = ' ';
289 }
cecfc5e7 290
d12e3536
VZ
291 break;
292 }
cecfc5e7 293
d12e3536
VZ
294 case 13 : line_len = 0; break;
295 case 10 : { line_len = 0; ++_gLineNo; } break;
cecfc5e7 296
d12e3536
VZ
297 default : ++line_len;
298 }
cecfc5e7 299
d12e3536
VZ
300 ++cur;
301 }
cecfc5e7 302
d12e3536 303 if ( cur >= _gSrcEnd ) return;
cecfc5e7 304
d12e3536 305 ++cur;
cecfc5e7 306
d12e3536
VZ
307 if ( *(cur-2) == '*' )
308 {
309 --level;
310 if ( level == 0 )
311 break;
312 }
313 else
314 if ( *cur == '*' )
315 {
316 ++cur;
317 ++cur;
cecfc5e7 318
d12e3536
VZ
319 ++level;
320 }
cecfc5e7 321
d12e3536 322 } while(1);
cecfc5e7
VZ
323}
324
325static inline void clear_commets_queue()
326{
d12e3536 327 _gCQSize = 0;
cecfc5e7
VZ
328}
329
330static inline void skip_quoted_string( char*& cur )
331{
d12e3536 332 ++cur; // skip first quote '"'
cecfc5e7 333
d12e3536
VZ
334 // check if quote wasn't prefixed
335 if ( *(cur-2) == '\\' )
336 return;
cecfc5e7 337
d12e3536
VZ
338 do
339 {
340 while ( *cur != '"' && cur < _gSrcEnd )
341 {
342 if ( *cur == 10 ) ++_gLineNo;
343 ++cur;
344 }
cecfc5e7 345
d12e3536 346 if ( cur >= _gSrcEnd ) return;
cecfc5e7 347
d12e3536 348 ++cur; // skip the last quote
cecfc5e7 349
d12e3536 350 // check if it wasn't prefixed
cecfc5e7 351
d12e3536
VZ
352 if ( *(cur-2) != '\\' )
353 break;
cecfc5e7 354
d12e3536 355 } while (1);
cecfc5e7
VZ
356}
357
358// skips subsequent white space and comments
359// (return false if the end of source code reached)
360
361static inline bool get_next_token( char*& cur )
362{
d12e3536
VZ
363 for( ; cur < _gSrcEnd; ++cur )
364 {
365 switch( *(cur) )
366 {
367 case ' ' : continue;
368 case '\t': continue;
369 case 13 : continue;
370
371 case 10 : { ++_gLineNo;continue; }
372
373 case '/' : skip_comments( cur );
374 --cur;
375 continue;
376
377 default : break;
378 };
379
380 break;
381 }
382
383 if ( cur >= _gSrcEnd )
8ad74db3 384 return false;
d12e3536 385 else
8ad74db3 386 return true;
cecfc5e7
VZ
387}
388
41964404 389static inline void skip_preprocessor_dir( wxChar*& cur )
cecfc5e7 390{
d12e3536
VZ
391 do
392 {
393 skip_to_eol(cur);
cecfc5e7 394
41964404 395 if ( *(cur-1) != _T('\\') )
d12e3536 396 break;
cecfc5e7 397
d12e3536
VZ
398 if ( cur < _gSrcEnd )
399 skip_eol( cur );
400 else
401 break;
cecfc5e7 402
d12e3536 403 } while(1);
cecfc5e7
VZ
404}
405
406static void skip_token( char*& cur )
407{
d12e3536
VZ
408 if ( *cur == '"' )
409 {
410 skip_quoted_string( cur );
411 return;
412 }
413
414 if ( *cur == ',' ||
415 *cur == ';' ||
416 *cur == ')' ||
417 *cur == '('
418 )
419 {
420 ++cur;
421 return;
422 }
cecfc5e7 423
f71f5a4f
VZ
424 // special case of "!=", "<=", ... 2 character composite tokens
425 if ( *cur == '<' ||
d12e3536
VZ
426 *cur == '>' ||
427 *cur == '=' ||
f71f5a4f
VZ
428 *cur == '!'
429 )
430 {
431 cur++;
432 if ( *cur == '=' )
433 cur++;
434
435 return;
436 }
437
d12e3536
VZ
438 ++cur; // leading character is always skipped
439
440 for( ; cur < _gSrcEnd ; ++cur )
441 {
442 switch ( *cur )
443 {
444 case ' ' : break;
445 case '\t': break;
446 case 13 : break;
447 case 10 : break;
448 case ',' : break;
449 case ';' : break;
450 case '<' : break;
451 case '>' : break;
452
453 // FIXME:: QUICK-HACK:: to treat scope resolution
454 // tokens are a part of the string - e.g. SomeSpace::SubName would
455 // become one token
456
457 case ':' : if ( *(cur+1) == ':' )
458 {
459 ++cur;
460 continue;
461 }
462
463 break;
464 case '=' : break;
465 case '(' : break;
466 case ')' : break;
467 case '{' : break;
468 case '}' : break;
469
470 default : continue;
471 };
472 break;
473 }
cecfc5e7
VZ
474}
475
476static inline size_t get_token_len( char* tok )
477{
d12e3536 478 char* start = tok;
cecfc5e7 479
d12e3536 480 skip_token( tok );
cecfc5e7 481
d12e3536 482 return size_t( tok - start );
cecfc5e7
VZ
483}
484
485// returns true, if given tokens are equel
486
487static inline bool cmp_tokens( char* tok1, char* tok2 )
488{
d12e3536
VZ
489 // NOTE:: the case one token includes
490 // other in it's entirely is not handled
cecfc5e7 491
d12e3536 492 size_t len = get_token_len( tok1 );
cecfc5e7 493
d12e3536 494 // assuming that tokens are non-zero length
cecfc5e7 495
d12e3536
VZ
496 do
497 {
498 if ( *(tok1++) != *(tok2++) )
8ad74db3 499 return false;
cecfc5e7 500
d12e3536 501 --len;
cecfc5e7 502
d12e3536 503 } while ( --len );
cecfc5e7 504
8ad74db3 505 return true;
cecfc5e7
VZ
506}
507
508static inline bool cmp_tokens_fast( char* tok1, char* tok2, size_t len )
509{
d12e3536
VZ
510 do
511 {
512 if ( *(tok1++) != *(tok2++) )
8ad74db3 513 return false;
cecfc5e7 514
d12e3536 515 } while ( --len );
cecfc5e7 516
8ad74db3 517 return true;
cecfc5e7
VZ
518}
519
520static inline void skip_tempalate_statement( char*& cur )
521{
d12e3536 522 size_t level = 0;
cecfc5e7 523
d12e3536
VZ
524 // go one level deeper
525 while( *cur != '<' && cur < _gSrcEnd )
526 {
527 if (*cur == 10 ) ++_gLineNo;
528 ++cur;
529 }
cecfc5e7 530
d12e3536
VZ
531 // FIXME:: template should be checked statement for
532 // comments inside of it
cecfc5e7 533
d12e3536
VZ
534 do
535 {
536 if ( *cur == '<' )
537 ++level;
538 else
539 --level;
cecfc5e7 540
d12e3536 541 ++cur; // skip '<' or '>' token
cecfc5e7 542
d12e3536
VZ
543 if ( level == 0 )
544 return;
cecfc5e7 545
d12e3536
VZ
546 while( *cur != '<' && *cur != '>' && cur < _gSrcEnd )
547 {
548 if (*cur == 10 ) ++_gLineNo;
549 ++cur;
550 }
cecfc5e7 551
d12e3536 552 } while (1);
cecfc5e7
VZ
553}
554
555static inline void skip_statement( char*& cur )
556{
d12e3536 557 for( ; cur < _gSrcEnd; ++cur )
cecfc5e7 558
d12e3536
VZ
559 switch (*cur)
560 {
561 case ';' : ++cur; // skip statement-terminator token
562 return;
cecfc5e7 563
d12e3536
VZ
564 case '"' : skip_quoted_string(cur);
565 --cur;
566 continue;
cecfc5e7 567
d12e3536 568 case 10 : ++_gLineNo;
cecfc5e7 569
d12e3536
VZ
570 continue;
571 case '/' : skip_comments( cur );
572 --cur;
573 continue;
574 default : continue;
575 }
cecfc5e7
VZ
576}
577
578// "reversed" versions of skip_token() and get_next_token()
579
580static inline void skip_token_back( char*& cur )
581{
d12e3536
VZ
582 // FIXME:: now, when moving backwards, neither strings nor
583 // comment blocks are checked
cecfc5e7 584
d12e3536 585 --cur; // skip to the trailing character
cecfc5e7 586
d12e3536
VZ
587 if ( *cur == ',' ||
588 *cur == ')' ||
589 *cur == '('
590 )
591 return;
cecfc5e7
VZ
592
593
d12e3536
VZ
594 for( ; cur < _gSrcEnd ; --cur )
595 {
596 switch ( *cur )
597 {
598 case ' ' : break;
599 case '\t': break;
600 case 13 : break;
601 case 10 : break;
602 case ',' : break;
603 case '(' : break;
cecfc5e7 604
d12e3536
VZ
605 default : continue;
606 };
cecfc5e7 607
d12e3536
VZ
608 break;
609 }
cecfc5e7 610
d12e3536 611 ++cur; // get to the leading character of the token
cecfc5e7
VZ
612}
613
614static inline void skip_next_token_back( char*& cur )
615{
d12e3536
VZ
616 --cur; // skip leading character of the current token
617
618 if ( *cur == ',' ||
619 *cur == ')' ||
620 *cur == '('
621 )
622 {
623 ++cur;
624 return;
625 }
626
627 for( ; cur < _gSrcEnd; --cur )
628 {
629 switch ( *cur )
630 {
631 case ' ' : continue;
632 case '\t': continue;
633 case 13 : continue;
634 case 10 : continue;
635 case ',' : continue;
636 case '(' : continue;
637
638 default : break;
639 };
640
641 break;
642 }
643
644 ++cur; // position after the trailing charcter of the prev token
cecfc5e7
VZ
645}
646
2af95167 647static wxString get_token_str( char* cur )
cecfc5e7 648{
2af95167 649 return wxString( cur, get_token_len( cur ) );
cecfc5e7
VZ
650}
651
652// skips token or whole expression which may have
653// nested expressions between '(' ')' brackets.
654//
655// Upon return, the cursor points to the terminating bracket ')',
656//
657// Return value is the size of the block
658
659static size_t skip_block( char*& cur )
660{
d12e3536
VZ
661 size_t level = 0; // nesting level
662
663 char* start = cur;
664
665 // NOTE:: assumed that block not necessarely starts
666 // with bracket rightaway
667
668 if ( *cur == '(' )
669 {
670 ++level;
671 }
672
673 do
674 {
675 skip_token( cur );
676
677 char* savedPos = cur;
678 int tmpLnNo;
679 store_line_no( tmpLnNo );
680
681 get_next_token( cur );
682
683 if ( cur >= _gSrcEnd ) return 0;
684
685 if ( *cur == '(' )
686 {
687 ++level;
688 }
689 else
690 if ( *cur == ')' )
691 {
692 if ( level == 0 )
693 {
694 cur = savedPos;
695 restore_line_no( tmpLnNo );
696
697 return size_t(cur-start);
698 }
699
700 --level;
701
702 if ( level == 0 )
703 {
704 ++cur;
705
706 // QUICK-HACK::to easily handle function prototypes ,
707 // it works, besause theoretically there should
708 // be no cast-expressions in non-implementation
709 // scope (e.g. "time( (long*)(ptr+1) )" should not
710 // appear in the declarations, thus it is most likelly
711 // for the ")(" fragment to be within a function
712 // prototype in the declarations scope
713
714 if ( *cur == '(' )
715 {
716 ++level;
717 continue;
718 }
719
720 else return size_t(cur-start);
721 }
722 }
723 else
724 {
725 if ( level == 0 )
726 {
727 cur = savedPos;
728 restore_line_no( tmpLnNo );
729
730 return size_t(cur-start);
731 }
732 }
733
734 } while(1);
cecfc5e7
VZ
735}
736
737// returns 0, if end of source reached
738static inline bool skip_imp_block( char*& cur )
739{
d12e3536
VZ
740 while( *cur != '{' && cur < _gSrcEnd )
741 {
742 skip_token( cur );
8ad74db3 743 if ( !get_next_token( cur ) ) return false;
d12e3536 744 }
cecfc5e7 745
d12e3536
VZ
746 while( *cur != '}' && cur < _gSrcEnd )
747 {
748 skip_token( cur );
8ad74db3 749 if ( !get_next_token( cur ) ) return false;
d12e3536 750 }
cecfc5e7 751
d12e3536 752 ++cur;
cecfc5e7 753
8ad74db3 754 return true;
cecfc5e7
VZ
755}
756
757static bool is_class_token( char*& cur )
758{
d12e3536 759 // FIXME:: the below mess should be cleaned in it's entirely
cecfc5e7 760
d12e3536
VZ
761 if ( *cur == 'i' )
762 if ( *(cur+1) == 'n' )
cecfc5e7 763
d12e3536 764 return cmp_tokens_fast( cur, "interface", 9 );
cecfc5e7 765
d12e3536
VZ
766 if ( *cur == 'c' )
767 if ( *(cur+1) == 'l' )
cecfc5e7 768
d12e3536 769 return cmp_tokens_fast( cur, "class", 5 );
cecfc5e7 770
d12e3536
VZ
771 if ( *cur == 's' )
772 if ( *(cur+1) == 't' )
cecfc5e7 773
d12e3536 774 return cmp_tokens_fast( cur, "struct", 6 );
cecfc5e7 775
d12e3536
VZ
776 if ( *cur == 'u' )
777 if ( *(cur+1) == 'n' )
cecfc5e7 778
d12e3536 779 return cmp_tokens_fast( cur, "union", 5 );
cecfc5e7 780
8ad74db3 781 return false;
cecfc5e7
VZ
782}
783
784inline static bool is_forward_decl( char* cur )
785{
d12e3536
VZ
786 do
787 {
788 switch( *cur )
789 {
8ad74db3
WS
790 case ':' : return false;
791 case '{' : return false;
792 case '(' : return false;
cecfc5e7 793
8ad74db3 794 case ';' : return true;
cecfc5e7 795
d12e3536
VZ
796 default : break;
797 };
cecfc5e7 798
d12e3536 799 ++cur;
cecfc5e7 800
d12e3536 801 } while (cur < _gSrcEnd); // prevent running out of bounds
cecfc5e7 802
8ad74db3 803 return false;
cecfc5e7
VZ
804}
805
806inline static bool is_function( char* cur, bool& isAMacro )
807{
8ad74db3 808 isAMacro = false;
cecfc5e7 809
d12e3536
VZ
810 int tmpLnNo;
811 store_line_no( tmpLnNo );
cecfc5e7 812
d12e3536 813 // NOTE:: comments and quoted strings are not checked here
cecfc5e7 814
d12e3536
VZ
815 // first,check for "single-line hanginging macros" like:
816 // ___UNICODE
817 //
cecfc5e7 818
d12e3536
VZ
819 char* eol = cur;
820 skip_to_eol( eol );
cecfc5e7 821
d12e3536
VZ
822 skip_token( cur );
823 get_next_token( cur );
cecfc5e7 824
d12e3536
VZ
825 if ( cur > eol )
826 {
8ad74db3 827 isAMacro = true;
d12e3536 828 restore_line_no( tmpLnNo );
cecfc5e7 829
8ad74db3 830 return true;
d12e3536 831 }
cecfc5e7 832
d12e3536 833 // it's not a macro, go to the begining of arg. list
cecfc5e7 834
d12e3536
VZ
835 do
836 {
837 // if bracket found, it's a function or a begining
838 // of some macro
839 if ( *cur == '(' )
840 {
841 restore_line_no( tmpLnNo );
8ad74db3 842 return true;
d12e3536 843 }
cecfc5e7 844
d12e3536
VZ
845 // end of statement found without any brackets in it
846 // - it cannot be a function
cecfc5e7 847
d12e3536
VZ
848 if ( *cur == ';' )
849 {
850 restore_line_no( tmpLnNo );
8ad74db3 851 return false;
d12e3536 852 }
cecfc5e7 853
d12e3536 854 ++cur;
cecfc5e7 855
d12e3536 856 } while( cur < _gSrcEnd);
cecfc5e7 857
d12e3536
VZ
858 isAMacro = 1;
859 restore_line_no( tmpLnNo );
860
8ad74db3 861 return false;
cecfc5e7
VZ
862}
863
864// upon return the cursor is positioned after the
d12e3536 865// terminating curly brace
cecfc5e7
VZ
866
867static inline void skip_scope_block( char*& cur )
868{
d12e3536 869 size_t level = 0;
cecfc5e7 870
d12e3536 871 for( ; cur < _gSrcEnd ; ++cur )
cecfc5e7 872
d12e3536
VZ
873 switch( *cur )
874 {
875 case '/' : skip_comments( cur );
876 --cur;
877 continue;
878 case '"' : skip_quoted_string( cur );
879 --cur;
880 continue;
881
882 case '{' : ++level;
883 continue;
884
885 case '}' :--level;
886 if ( level == 0 )
887 {
888 ++cur; // skip final closing curly brace
889 return;
890 }
891
892 case 10 : ++_gLineNo; continue;
893
894 default : continue;
895 };
cecfc5e7
VZ
896}
897
898// moves tokens like '*' '**', '***', '&' from the name
899// to the type
900
821d644d
WS
901static void arrange_indirection_tokens_between( wxString& type,
902 wxString& identifier )
cecfc5e7 903{
d12e3536 904 // TBD:: FIXME:: return value of operators !
cecfc5e7 905
821d644d
WS
906 while ( identifier[0u] == _T('*') ||
907 identifier[0u] == _T('&')
d12e3536
VZ
908 )
909 {
753287c1 910 type += identifier[0u];
d12e3536 911 identifier.erase(0,1);
cecfc5e7 912
d12e3536
VZ
913 if ( !identifier.length() ) return;
914 }
cecfc5e7
VZ
915}
916
917
918// the only function where multi-lang keyword map is accessed
919
920static bool is_keyword( char* cur )
921{
d12e3536
VZ
922 size_t len = get_token_len( cur );
923
924 // put a terminating zero after the given token
925 char tmp = *(cur + len);
926 *(cur+len) = '\0';
cecfc5e7 927
d12e3536 928 KeywordMapT::iterator i;
cecfc5e7 929
d12e3536
VZ
930 i = __gMultiLangMap.find( cur );
931
932 // restore original character suppresed by terminating zero
933 *(cur + len) = tmp;
cecfc5e7 934
59734eb5 935 return i == __gMultiLangMap.end() ? false : true;
cecfc5e7
VZ
936}
937
1b75cbf9
WS
938static inline void get_string_between( wxChar* start, wxChar* end,
939 wxString* pStr )
cecfc5e7 940{
d12e3536 941 char saved = *end;
cecfc5e7 942
1b75cbf9 943 *end = _T('\0');
d12e3536
VZ
944 *pStr = start;
945 *end = saved;
cecfc5e7
VZ
946}
947
e48f6880 948static wxChar* set_comment_text( wxString& text, wxChar* start )
cecfc5e7 949{
e48f6880 950 wxChar* end = start;
cecfc5e7 951
d12e3536
VZ
952 // to avoid poluting the queue with this comment
953 _gLastSuppresedComment = start;
cecfc5e7 954
d12e3536 955 skip_comments( end );
cecfc5e7 956
e48f6880 957 if ( *(end-1) == _T('/') )
d12e3536 958 end -= 2;
cecfc5e7 959
d12e3536 960 start += 2;
cecfc5e7 961
d12e3536 962 // skip multiple leading '/''s or '*''s
e48f6880
WS
963 while( *start == _T('/') && start < end ) ++start;
964 while( *start == _T('*') && start < end ) ++start;
cecfc5e7 965
d12e3536 966 get_string_between( start, end, &text );
cecfc5e7 967
d12e3536 968 return end;
cecfc5e7
VZ
969}
970
971/***** Implementation for class CJSourceParser *****/
972
973CJSourceParser::CJSourceParser( bool collectCommnets, bool collectMacros )
d12e3536
VZ
974 : mpStart(0),
975 mpEnd(0),
976 mpCurCtx( 0 ),
977 mCommentsOn( collectCommnets ),
978 mMacrosOn ( collectMacros )
cecfc5e7 979{
d12e3536 980 check_keyword_map();
cecfc5e7
VZ
981}
982
983spFile* CJSourceParser::Parse( char* start, char* end )
984{
d12e3536
VZ
985 // set up state variables
986 mCurVis = SP_VIS_PRIVATE;
987
988 spFile* pTopCtx = new spFile();
989 mpCurCtx = pTopCtx;
990
991 mIsVirtual = 0;
992 mIsTemplate = 0;
993 mNestingLevel = 0;
994
b6317810 995 m_cur = start;
d12e3536
VZ
996
997 mpStart = start;
998 mpEnd = end;
999
1000 _gSrcEnd = mpEnd; // let all the C-functions "smell" the end of file
1001 _gSrcStart = start;
1002
1003 _gLineNo = 0;
1004
1005 clear_commets_queue();
1006
1007 // main parsing loop
1008
1009 do
1010 {
b6317810 1011 if ( !get_next_token( m_cur ) )
d12e3536
VZ
1012 // end of source reached
1013 return pTopCtx;
1014
b6317810 1015 if ( memcmp( m_cur, "ScriptSection( const string&",
d12e3536
VZ
1016 strlen( "ScriptSection( const string&" )
1017 ) == 0
1018 )
1019 {
8ad74db3
WS
1020 // int o = 0;
1021 // ++o;
d12e3536
VZ
1022 }
1023
b6317810 1024 switch (*m_cur)
d12e3536
VZ
1025 {
1026 case '#' :
1027 {
b6317810 1028 AddMacroNode( m_cur );
d12e3536
VZ
1029 continue;
1030 }
1031
1032 case ':' :
1033 {
b6317810 1034 skip_token( m_cur );
d12e3536
VZ
1035 continue;
1036 }
1037
1038 case ';' :
1039 {
b6317810 1040 skip_token( m_cur );
d12e3536
VZ
1041 continue;
1042 }
1043
1044 case ')' :
1045 {
b6317810 1046 skip_token( m_cur );
d12e3536
VZ
1047 continue;
1048 }
1049
1050 case '=' :
1051 {
b6317810 1052 skip_token( m_cur );
d12e3536
VZ
1053 continue;
1054 }
1055
1056 default: break;
1057 }
cecfc5e7 1058
59734eb5 1059 // 'const' is a part of the return type, not a keyword here
b6317810 1060 if ( strncmp(m_cur, "const", 5) != 0 && is_keyword( m_cur ) )
d12e3536
VZ
1061 {
1062 // parses, token, if token identifies
1063 // the container context (e.g. class/namespace)
1064 // the corresponding context object is created
1065 // and set as current context
cecfc5e7 1066
b6317810 1067 ParseKeyword( m_cur );
d12e3536
VZ
1068 continue;
1069 }
cecfc5e7 1070
b6317810 1071 if ( *m_cur >= _T('0') && *m_cur <= _T('9') )
d12e3536 1072 {
b6317810 1073 skip_token( m_cur );
d12e3536
VZ
1074 continue;
1075 }
cecfc5e7 1076
b6317810 1077 if ( *m_cur == _T('}') )
d12e3536
VZ
1078 {
1079 if ( mCurCtxType != SP_CTX_CLASS )
1080 {
1081 // FOR NOW:: disable the below assertion
cecfc5e7 1082
d12e3536
VZ
1083 // DBG:: unexpected closing-bracket found
1084 //ASSERT(0);
cecfc5e7 1085
b6317810 1086 skip_token( m_cur ); // just skip it
d12e3536
VZ
1087 continue;
1088 }
cecfc5e7 1089
d12e3536
VZ
1090 if ( mpCurCtx->GetType() == SP_CTX_CLASS )
1091 {
b6317810 1092 int curOfs = ( (m_cur+1) - _gSrcStart );
cecfc5e7 1093
d12e3536
VZ
1094 mpCurCtx->mContextLength = ( curOfs - mpCurCtx->mSrcOffset );
1095 }
1096
1097 --mNestingLevel;
cecfc5e7 1098
d12e3536
VZ
1099 // terminate operation/class/namespace context
1100 // TBD:: check if it's really this type of context
cecfc5e7 1101
d12e3536
VZ
1102 wxASSERT( mpCurCtx );
1103 mpCurCtx = mpCurCtx->GetOutterContext();
1104 wxASSERT( mpCurCtx );
cecfc5e7 1105
d12e3536
VZ
1106 if ( mNestingLevel == 0 )
1107 {
cecfc5e7 1108
d12e3536 1109 mCurCtxType = SP_CTX_FILE;
cecfc5e7 1110
d12e3536
VZ
1111 // not-nested class delclaration finished,
1112 // rest template flag in any case
1113 mIsTemplate = 0;
1114 }
cecfc5e7 1115
b6317810 1116 skip_token( m_cur );
d12e3536
VZ
1117 continue;
1118 }
cecfc5e7 1119
8ad74db3 1120 bool isAMacro = false;
cecfc5e7 1121
b6317810 1122 if ( is_function( m_cur, isAMacro ) )
d12e3536
VZ
1123 {
1124 if ( isAMacro )
1125 {
b6317810 1126 skip_token( m_cur );
d12e3536
VZ
1127 continue;
1128 }
cecfc5e7 1129
b6317810 1130 char* savedPos = m_cur;
cecfc5e7 1131
d12e3536
VZ
1132 int tmpLnNo;
1133 store_line_no( tmpLnNo );
8ad74db3 1134 wxUnusedVar( tmpLnNo );
cecfc5e7 1135
8ad74db3 1136 isAMacro = false;
cecfc5e7 1137
b6317810 1138 if ( !ParseNameAndRetVal( m_cur, isAMacro ) )
d12e3536
VZ
1139 {
1140 if ( !isAMacro )
1141 {
b6317810
WS
1142 m_cur = savedPos;
1143 SkipFunction( m_cur );
d12e3536
VZ
1144 }
1145 continue;
1146 }
cecfc5e7 1147
b6317810 1148 if ( !ParseArguments( m_cur ) )
d12e3536
VZ
1149 {
1150 // failure while parsing arguments,
1151 // remove enclosing operation context
cecfc5e7 1152
d12e3536
VZ
1153 spContext* pFailed = mpCurCtx;
1154 mpCurCtx = mpCurCtx->GetOutterContext();
1155 mpCurCtx->RemoveChild( pFailed );
cecfc5e7 1156
b6317810
WS
1157 skip_to_eol( m_cur );
1158 //m_cur = savedPos;
d12e3536
VZ
1159 }
1160 else
1161 {
1162 // otherwise, successfully close operation context:
cecfc5e7 1163
d12e3536 1164 clear_commets_queue();
cecfc5e7 1165
b6317810 1166 SkipFunctionBody( m_cur );
cecfc5e7 1167
d12e3536 1168 mpCurCtx = mpCurCtx->GetOutterContext();
cecfc5e7 1169
d12e3536
VZ
1170 // DBG::
1171 wxASSERT( mpCurCtx );
cecfc5e7 1172
d12e3536
VZ
1173 }
1174 }
1175 else // otherwise it's declaration of a variable;
1176 {
1177 // now, the cursor point to the end of statement (';' token)
cecfc5e7 1178
d12e3536
VZ
1179 if ( mCurCtxType != SP_CTX_CLASS )
1180 {
1181 // non-class members are ignored
cecfc5e7 1182
b6317810 1183 skip_token( m_cur ); // skip the end of statement
d12e3536
VZ
1184 continue;
1185 }
cecfc5e7 1186
b6317810 1187 ParseMemberVar( m_cur );
d12e3536 1188 }
cecfc5e7 1189
d12e3536 1190 } while( 1 );
cecfc5e7
VZ
1191}
1192
e49cde67 1193void CJSourceParser::AttachComments( spContext& ctx, wxChar* cur )
cecfc5e7 1194{
d12e3536 1195 if ( !mCommentsOn ) return;
cecfc5e7 1196
d12e3536 1197 MCommentListT& lst = ctx.GetCommentList();
cecfc5e7 1198
b6317810 1199 wxChar* prevComEnd = 0;
cecfc5e7 1200
d12e3536
VZ
1201 int tmpLnNo;
1202 store_line_no( tmpLnNo );
cecfc5e7 1203
d12e3536 1204 // attach comments which were found before the given context
cecfc5e7 1205
d12e3536
VZ
1206 for( int i = 0; i != _gCQSize; ++i )
1207 {
1208 spComment* pComment = new spComment();
1209 lst.push_back( pComment );
cecfc5e7 1210
d12e3536 1211 // find the end of comment
b6317810 1212 wxChar* start = _gCommentsQueue[i];
cecfc5e7 1213
b6317810 1214 pComment->mIsMultiline = ( *(start+1) == _T('*') );
cecfc5e7 1215
d12e3536
VZ
1216 // first comment in the queue and multiline
1217 // comments are always treated as a begining
1218 // of the new paragraph in the comment text
cecfc5e7 1219
d12e3536 1220 if ( i == 0 )
b6317810 1221 {
8ad74db3 1222 pComment->mStartsPar = true;
b6317810
WS
1223 }
1224 else if ( pComment->mIsMultiline )
1225 {
8ad74db3 1226 pComment->mStartsPar = true;
b6317810 1227 }
d12e3536
VZ
1228 else
1229 {
1230 // find out wheather there is a new-line
1231 // between to adjecent comments
cecfc5e7 1232
b6317810 1233 wxChar* prevLine = start;
d12e3536 1234 skip_to_prev_line(prevLine);
cecfc5e7 1235
d12e3536 1236 if ( prevLine >= prevComEnd )
8ad74db3 1237 pComment->mStartsPar = true;
d12e3536 1238 else
8ad74db3 1239 pComment->mStartsPar = false;
d12e3536 1240 }
cecfc5e7 1241
e49cde67 1242 prevComEnd = set_comment_text( pComment->m_Text, start );
d12e3536
VZ
1243 }
1244
d12e3536
VZ
1245 // attach comments which are at the end of the line
1246 // of the given context (if any)
cecfc5e7 1247
d12e3536
VZ
1248 if ( skip_to_next_comment_in_the_line( cur ) )
1249 {
1250 spComment* pComment = new spComment();
1251 lst.push_back( pComment );
cecfc5e7 1252
e49cde67 1253 set_comment_text( pComment->m_Text, cur );
cecfc5e7 1254
d12e3536 1255 pComment->mStartsPar = 1;
b6317810 1256 pComment->mIsMultiline = ( *(cur+1) == _T('*') );
cecfc5e7 1257
d12e3536
VZ
1258 // mark this comment, so that it would not
1259 // get in the comments list of the next context
1260 _gLastSuppresedComment = cur;
1261 }
cecfc5e7 1262
d12e3536 1263 restore_line_no( tmpLnNo );
cecfc5e7 1264
d12e3536 1265 clear_commets_queue();
cecfc5e7
VZ
1266}
1267
c69a7d10 1268void CJSourceParser::AddMacroNode( wxChar*& cur )
cecfc5e7 1269{
c69a7d10 1270 wxChar* start = cur;
d12e3536
VZ
1271
1272 int lineNo = get_line_no();
cecfc5e7 1273
d12e3536 1274 skip_preprocessor_dir( cur );
cecfc5e7 1275
d12e3536
VZ
1276 int tmpLnNo;
1277 store_line_no( tmpLnNo );
cecfc5e7 1278
d12e3536 1279 if ( !mMacrosOn ) return;
cecfc5e7 1280
d12e3536
VZ
1281 spPreprocessorLine* pPL = new spPreprocessorLine();
1282 pPL->mSrcLineNo = lineNo;
cecfc5e7 1283
d12e3536 1284 AttachComments( *pPL, cur );
cecfc5e7 1285
c69a7d10 1286 get_string_between( start, cur, &pPL->m_Line );
d12e3536
VZ
1287
1288 ++start; // skip '#'
1289 get_next_token( start );
1290
1291 pPL->mDefType = SP_PREP_DEF_OTHER;
1292
1293 // if we found a definition or redefinition,
1294 // determine the type exactly and assign
1295 // a name to the context
1296
c69a7d10 1297 if ( *start == _T('d') )
d12e3536 1298 {
c69a7d10 1299 if ( cmp_tokens_fast( start, _T("define"), 6 ) )
d12e3536
VZ
1300 {
1301 char* tok = start+6;
cecfc5e7 1302
d12e3536 1303 get_next_token( tok );
cecfc5e7 1304
8bc17f14 1305 pPL->m_Name = get_token_str( tok );
cecfc5e7 1306
d12e3536
VZ
1307 skip_token( tok );
1308 get_next_token( tok);
cecfc5e7 1309
cecfc5e7 1310
d12e3536
VZ
1311 if ( tok > cur )
1312 pPL->mDefType = SP_PREP_DEF_DEFINE_SYMBOL;
1313 else
1314 pPL->mDefType = SP_PREP_DEF_REDEFINE_SYMBOL;
1315 }
1316 }
c69a7d10 1317 else if ( *start == _T('i') )
d12e3536 1318 {
c69a7d10 1319 if ( cmp_tokens_fast( start, _T("include"), 7 ) )
d12e3536
VZ
1320 {
1321 pPL->mDefType = SP_PREP_DEF_INCLUDE_FILE;
1322 }
c69a7d10 1323 else if ( *++start == _T('f') )
d12e3536
VZ
1324 {
1325 // either "#if" or "#ifdef"
1326 cur = start;
1327 skip_token( cur );
1328 get_next_token( cur );
cecfc5e7 1329
2af95167 1330 wxString condition = get_token_str( cur );
cecfc5e7 1331
d12e3536 1332 // currently, everything except '0' is true
c69a7d10 1333 if ( condition == _T("0") ) {
d12e3536
VZ
1334 // skip until the following else or enif
1335 while ( cur < _gSrcEnd ) {
1336 skip_to_eol( cur );
1337 skip_eol( cur );
cecfc5e7 1338
d12e3536 1339 get_next_token( cur );
c69a7d10 1340 if ( *cur++ == _T('#') && *cur == _T('e') )
d12e3536
VZ
1341 break;
1342 }
1343 }
cecfc5e7 1344
d12e3536
VZ
1345 // TODO parse the condition...
1346 }
1347 }
c69a7d10 1348 else if ( cmp_tokens_fast( start, _T("else"), 4 ) )
d12e3536
VZ
1349 {
1350 // skip until "#endif"
1351 while ( cur < _gSrcEnd ) {
1352 skip_to_eol( cur );
1353 skip_eol( cur );
1354
1355 get_next_token( cur );
c69a7d10 1356 if ( *cur++ == _T('#') && cmp_tokens_fast( cur, "endif", 5 ) )
d12e3536
VZ
1357 break;
1358 }
1359 }
cecfc5e7 1360
d12e3536 1361 mpCurCtx->AddMember( pPL );
cecfc5e7 1362
d12e3536
VZ
1363 skip_to_eol( cur );
1364 skip_eol( cur );
cecfc5e7 1365
d12e3536 1366 restore_line_no( tmpLnNo );
cecfc5e7 1367
d12e3536 1368 clear_commets_queue();
cecfc5e7
VZ
1369}
1370
1371void CJSourceParser::ParseKeyword( char*& cur )
1372{
d12e3536
VZ
1373 // analyze token, which identifies the begining of a new context
1374
1375 if ( CheckVisibilty( cur ) )
1376 {
1377 skip_token( cur );
1378 return;
1379 }
1380
1381 if ( is_class_token( cur ) )
1382 {
1383 if ( is_forward_decl( cur ) )
1384 {
1385 // forward declarations are ignored;
1386 skip_token( cur );
1387 return;
1388 }
1389
1390 if ( mNestingLevel == 0 )
1391 {
1392 // change context form global class context
1393 mCurCtxType = SP_CTX_CLASS;
1394 }
1395
1396 ++mNestingLevel;
1397
1398 // add information about new class (name, inheritance, etc)
1399 AddClassNode( cur );
1400
1401 // the default visiblity for class members is 'private'
1402 mCurVis = SP_VIS_PRIVATE;
1403
1404 return;
1405 }
1406
1407 size_t len = get_token_len( cur );
1408
1409 if ( cmp_tokens_fast( cur, "typedef", len ) )
1410 {
1411 skip_token(cur);
1412 get_next_token(cur);
1413
1414 if ( cmp_tokens_fast( cur, "struct", len ) ||
1415 cmp_tokens_fast( cur, "union", len ) ||
1416 cmp_tokens_fast( cur, "class", len )
1417 )
1418 {
1419 if ( mNestingLevel == 0 )
1420 {
1421 // change context form global class context
1422 mCurCtxType = SP_CTX_CLASS;
1423 }
1424
1425 ++mNestingLevel;
1426
1427 // add information about new class (name, inheritance, etc)
1428 AddClassNode( cur );
1429
1430 // the default visiblity for class members is 'private'
1431 mCurVis = SP_VIS_PRIVATE;
1432
1433 return;
1434
1435 // FOR NOW:: typedef struct, etc are also ignored
1436 //skip_scope_block( cur );
1437 }
1438
1439 if ( cmp_tokens_fast( cur, "enum", len ) )
1440 {
1441 AddEnumNode( cur );
1442 return;
1443 }
1444
1445 AddTypeDefNode( cur );
1446
1447 return;
1448 }
1449
1450 if ( cmp_tokens_fast( cur, "enum", len ) )
1451 {
1452 AddEnumNode( cur );
1453 return;
1454 }
1455
1456 if ( cmp_tokens_fast( cur, "extern", len ) )
1457 {
1458 // extern's are ignored (both extern "C" and extern vars)
1459 while ( *cur != '{' &&
1460 *cur != ';' )
1461 {
1462 skip_token( cur );
1463 get_next_token( cur );
1464 }
1465 return;
1466
1467 }
1468 if ( cmp_tokens_fast( cur, "enum", len ) )
1469 {
1470 // enumeration blocks are ignored
1471
1472 skip_scope_block( cur );
1473
1474 get_next_token( cur );
1475 skip_token( cur ); // skip ';' token;
1476 return;
1477 }
1478
1479 if ( cmp_tokens_fast( cur, "package", len ) )
1480 {
1481 // packages are ignored
1482 skip_statement( cur );
1483 return;
1484 };
1485
1486 if ( cmp_tokens_fast( cur, "import", len ) )
1487 {
1488 // import statements are ignored
1489 skip_statement( cur );
1490 return;
1491 }
1492
1493 if ( cmp_tokens_fast( cur, "virtual", len ) )
1494 {
1495 // probably the virtual method is in front of us;
1496 mIsVirtual = 1;
1497 skip_token( cur );
1498 return;
1499 }
1500
1501 if ( cmp_tokens_fast( cur, "template", len ) )
1502 {
1503 mIsTemplate = 1;
1504 skip_tempalate_statement( cur );
1505 return;
1506 }
1507
1508 if ( cmp_tokens_fast( cur, "friend", len ) )
1509 {
1510 skip_statement( cur );
1511 return;
1512 }
1513
1514 // ingnore "unsigificant" tokens (i.e. which do not
1515 // affect the current parsing context)
1516
1517 skip_token( cur );
cecfc5e7
VZ
1518}
1519
1520bool CJSourceParser::ParseNameAndRetVal( char*& cur, bool& isAMacro )
1521{
8ad74db3 1522 isAMacro = false;
cecfc5e7 1523
d12e3536
VZ
1524 // FOR NOW:: all functions in the global
1525 // scope are ignored
cecfc5e7 1526
d12e3536 1527 int lineNo = get_line_no();
cecfc5e7 1528
d12e3536 1529 char* start = cur;
cecfc5e7 1530
59734eb5 1531 bool isVirtual = false;
d12e3536
VZ
1532 while( *cur != '(' )
1533 {
59734eb5
VZ
1534 if ( get_token_str( cur ) == "virtual" )
1535 isVirtual = true;
1536
d12e3536 1537 skip_token( cur );
8ad74db3 1538 if ( !get_next_token( cur ) ) return false;
d12e3536 1539 }
cecfc5e7 1540
d12e3536
VZ
1541 char* bracketPos = cur;
1542 char* savedPos = cur + 1;
cecfc5e7 1543
d12e3536
VZ
1544 int tmpLnNo;
1545 store_line_no( tmpLnNo );
cecfc5e7 1546
d12e3536
VZ
1547 // skip gap between function name and start of paramters list
1548 while ( *(cur-1) == ' ' )
1549 --cur;
cecfc5e7 1550
d12e3536 1551 // check if it's not a macro, and let plugin handle it, if so
cecfc5e7 1552
d12e3536
VZ
1553 if ( mpPlugin )
1554 {
1555 skip_token_back( cur );
cecfc5e7 1556
d12e3536 1557 char* tmp = cur;
cecfc5e7 1558
d12e3536
VZ
1559 if ( mpPlugin->CanUnderstandContext( tmp, _gSrcEnd, mpCurCtx ) )
1560 {
1561 cur = tmp;
cecfc5e7 1562
d12e3536 1563 mpPlugin->ParseContext( _gSrcStart, cur, _gSrcEnd, mpCurCtx );
cecfc5e7 1564
8ad74db3 1565 isAMacro = true;
cecfc5e7 1566
8ad74db3 1567 return false;
d12e3536
VZ
1568 }
1569 }
cecfc5e7 1570
d12e3536 1571 spOperation* pOp = new spOperation();
cecfc5e7 1572
d12e3536
VZ
1573 pOp->mSrcLineNo = lineNo;
1574 pOp->mSrcOffset = int( start - _gSrcStart );
1575 pOp->mHeaderLength = int( bracketPos - start );
1576 if ( mpCurCtx->GetContextType() == SP_CTX_CLASS )
8bc17f14 1577 pOp->mScope = mpCurCtx->m_Name;
cecfc5e7 1578
d12e3536
VZ
1579 mpCurCtx->AddMember( pOp );
1580 pOp->mVisibility = mCurVis;
59734eb5 1581 pOp->mIsVirtual = isVirtual;
cecfc5e7 1582
d12e3536
VZ
1583 // add comments about operation
1584 AttachComments( *pOp, cur );
cecfc5e7 1585
d12e3536
VZ
1586 // go backwards to method name
1587 skip_token_back( cur );
cecfc5e7 1588
8bc17f14 1589 pOp->m_Name = get_token_str( cur );
cecfc5e7 1590
f71f5a4f 1591 // checker whether it's not an operator
8bc17f14 1592 char chFirst = *pOp->m_Name.c_str();
d12e3536 1593 if ( !isalpha(chFirst) && chFirst != '_' && chFirst != '~' ) {
f71f5a4f 1594 // skip 'operator'
d12e3536 1595 skip_next_token_back( cur );
f71f5a4f
VZ
1596 skip_token_back( cur );
1597
2af95167 1598 wxString lastToken = get_token_str( cur );
d12e3536 1599 if ( lastToken == "operator" ) {
8bc17f14
WS
1600 lastToken += pOp->m_Name;
1601 pOp->m_Name = lastToken;
f71f5a4f 1602 }
d12e3536 1603 else {
f71f5a4f
VZ
1604 // ok, it wasn't an operator after all
1605 skip_token( cur );
1606 }
1607 }
8bc17f14 1608 else if ( pOp->m_Name == "operator" ) {
d12e3536
VZ
1609 skip_token( cur );
1610 get_next_token( cur );
2af95167 1611 wxString oper = get_token_str( cur );
f71f5a4f 1612
8bc17f14 1613 pOp->m_Name += oper;
d12e3536 1614 }
cecfc5e7 1615
d12e3536
VZ
1616 // go backwards to method return type
1617 skip_next_token_back( cur );
cecfc5e7 1618
d12e3536
VZ
1619 if ( cur >= start )
1620 {
2af95167 1621 wxString rettype = wxString( start, size_t( cur-start ) );
42389ac7 1622 // FIXME just for now...
2af95167
WS
1623 wxString::size_type pos = 0;
1624 wxString toerase("WXDLLEXPORT ");
1625 while((pos = rettype.find(toerase, pos)) != wxString::npos)
42389ac7 1626 rettype.erase(pos, toerase.length());
821d644d 1627 pOp->m_RetType = rettype;
d12e3536 1628 }
cecfc5e7 1629
821d644d 1630 arrange_indirection_tokens_between( pOp->m_RetType, pOp->m_Name );
cecfc5e7 1631
d12e3536
VZ
1632 cur = savedPos;
1633 restore_line_no( tmpLnNo );
cecfc5e7 1634
d12e3536
VZ
1635 // now, enter operation context
1636 mpCurCtx = pOp;
cecfc5e7 1637
8ad74db3 1638 return true;
cecfc5e7
VZ
1639}
1640
1641bool CJSourceParser::ParseArguments( char*& cur )
1642{
d12e3536 1643 // DANGER-MACROS::
cecfc5e7 1644
d12e3536
VZ
1645 // now cursor position is right after the first opening bracket
1646 // of the function declaration
cecfc5e7 1647
d12e3536
VZ
1648 char* blocks [16]; // used exclusivelly for iterative "lean out"
1649 // of macros and misc. not-obviouse grammar
1650 // (dirty,, but we cannot do it very nice,
1651 // we're not preprocessor-free C/C++ code)
1652 int blockSizes[16];
cecfc5e7 1653
d12e3536
VZ
1654 do
1655 {
1656 size_t blocksSkipped = 0;
cecfc5e7 1657
d12e3536 1658 get_next_token( cur );
cecfc5e7 1659
8ad74db3 1660 bool first_blk = true;
cecfc5e7 1661
d12e3536
VZ
1662 while( *cur != ')' && *cur != ',' )
1663 {
1664 blocks[blocksSkipped] = cur;
cecfc5e7 1665
d12e3536
VZ
1666 if ( first_blk )
1667 {
1668 char* prev = cur;
1669 skip_token( cur );
cecfc5e7 1670
d12e3536 1671 blockSizes[blocksSkipped] = size_t(cur-prev);
cecfc5e7 1672
d12e3536
VZ
1673 first_blk = 0;
1674 }
1675 else
1676 blockSizes[blocksSkipped] = skip_block( cur );
cecfc5e7 1677
d12e3536
VZ
1678 get_next_token( cur );
1679 ++blocksSkipped;
1680 }
cecfc5e7
VZ
1681
1682
d12e3536
VZ
1683 if ( blocksSkipped == 1 )
1684 {
1685 // check if the empty arg. list stressed with "void" inside
f71f5a4f
VZ
1686 if ( cmp_tokens_fast( blocks[0] , "void", 4 ) )
1687 {
1688 cur++; // skip ')'
1689
d12e3536 1690 break;
f71f5a4f 1691 }
cecfc5e7 1692
d12e3536
VZ
1693 // FIXME:: TBD:: K&R-style function declarations!
1694
1695 // if only one block enclosed, than it's probably
1696 // some macro, there should be at least two blocks,
1697 // one for argument type and another for it's identifier
8ad74db3 1698 return false;
d12e3536 1699 }
cecfc5e7 1700
d12e3536
VZ
1701 if ( blocksSkipped == 0 )
1702 {
1703 if ( *cur == 10 ) ++_gLineNo;
1704 ++cur; // skip ')'
cecfc5e7 1705
d12e3536
VZ
1706 break; // function without paramters
1707 }
59734eb5 1708
d12e3536
VZ
1709 // we should be in the operation context now
1710 spOperation* pOp = (spOperation*)mpCurCtx;
cecfc5e7 1711
d12e3536 1712 spParameter* pPar = new spParameter();
cecfc5e7 1713
d12e3536
VZ
1714 pOp->AddMember( pPar );
1715 // FOR NOW:: line number is not exact if argument list is mutiline
1716 pPar->mSrcLineNo = get_line_no();
cecfc5e7 1717
d12e3536
VZ
1718 size_t nameBlock = blocksSkipped - 1;
1719 size_t typeBlock = nameBlock - 1;
cecfc5e7 1720
d12e3536
VZ
1721 // check if default values present
1722 if ( *blocks[typeBlock] == '=' )
1723 {
1724 // expressions like "int = 5" are ignored,
1725 // since name for paramters is required
1726 if ( blocksSkipped == 3 )
1727 {
1728 if ( *cur == ')' )
1729 {
1730 ++cur;
1731 break;
1732 }
1733 else
1734 continue;
1735 }
cecfc5e7 1736
fa1af598 1737 pPar->m_InitVal = wxString( blocks[nameBlock], blockSizes[nameBlock] );
cecfc5e7 1738
d12e3536
VZ
1739 nameBlock = nameBlock - 2; // skip '=' token and default value block
1740 typeBlock = nameBlock - 1;
1741 }
cecfc5e7 1742
d12e3536
VZ
1743 // attach comments about the parameter
1744 AttachComments( *pPar, blocks[nameBlock] );
cecfc5e7 1745
d12e3536 1746 // retrieve argument name
2af95167 1747 pPar->m_Name = wxString( blocks[nameBlock], blockSizes[nameBlock] );
cecfc5e7 1748
d12e3536 1749 // retreive argument type
cecfc5e7 1750
d12e3536
VZ
1751 size_t len = blockSizes[ typeBlock ];
1752 len = size_t ( (blocks[ typeBlock ] + len) - blocks[ 0 ] );
cecfc5e7 1753
2af95167 1754 pPar->m_Type = wxString( blocks[0], len );
cecfc5e7 1755
821d644d 1756 arrange_indirection_tokens_between( pPar->m_Type, pPar->m_Name );
cecfc5e7 1757
d12e3536
VZ
1758 if ( *cur == ')' )
1759 {
1760 ++cur;
1761 break;
1762 }
cecfc5e7 1763
d12e3536
VZ
1764 ++cur; // skip comma
1765 get_next_token(cur);
cecfc5e7 1766
d12e3536 1767 } while(1);
cecfc5e7 1768
59734eb5
VZ
1769 // skip possible whitespace between ')' and following "const"
1770 while ( isspace(*cur) )
1771 cur++;
1772
d12e3536
VZ
1773 // check if it was really a function not a macro,
1774 // if so, than it should be terminated with semicolon ';'
1775 // or opening implemenetaton bracket '{'
1776
1777 char* tok = cur;
1778
1779 int tmpLnNo;
1780 store_line_no( tmpLnNo );
1781
8ad74db3
WS
1782 bool result = true;
1783
d12e3536
VZ
1784 do
1785 {
1786 if ( *tok == '{' || *tok == ';' )
1787 {
1788 restore_line_no(tmpLnNo);
8ad74db3 1789 break;
d12e3536
VZ
1790 }
1791
1792 // check for unexpected tokens
1793 if ( *tok == '=' || *tok == '0' )
1794 {
1795 skip_token(tok);
8ad74db3 1796 if ( !get_next_token(tok) ) return false;
d12e3536
VZ
1797 continue;
1798 }
1799
8ad74db3 1800 if ( *tok == '}' ) return false;
d12e3536
VZ
1801
1802 // if initialization list found
1803 if ( *tok == ':' )
1804 {
1805 restore_line_no(tmpLnNo);
8ad74db3 1806 break;
d12e3536
VZ
1807 }
1808
1809 if ( cmp_tokens_fast( tok, "const", 5 ) )
1810 {
59734eb5
VZ
1811 ((spOperation*)mpCurCtx)->mIsConstant = true;
1812
d12e3536 1813 skip_token(tok);
8ad74db3 1814 if ( !get_next_token(tok) ) return false;
d12e3536
VZ
1815 continue;
1816 }
1817
8ad74db3 1818 if ( CheckVisibilty( tok ) ) return false;
cecfc5e7 1819
d12e3536 1820 // if next context found
8ad74db3 1821 if ( is_keyword( tok ) ) return false;
cecfc5e7 1822
d12e3536 1823 skip_token(tok);
8ad74db3 1824 if ( !get_next_token(tok) ) return false;
cecfc5e7 1825
d12e3536 1826 } while(1);
cecfc5e7 1827
8ad74db3 1828 return result;
cecfc5e7
VZ
1829}
1830
1831void CJSourceParser::ParseMemberVar( char*& cur )
1832{
d12e3536 1833 MMemberListT& members = mpCurCtx->GetMembers();
cecfc5e7 1834
8ad74db3 1835 bool firstMember = true;
cecfc5e7 1836
2af95167 1837 wxString type;
cecfc5e7 1838
d12e3536
VZ
1839 // jump to the end of statement
1840 // and start collecting same-type varibles
1841 // back-to-front towards the type identifier
cecfc5e7 1842
d12e3536
VZ
1843 skip_statement( cur );
1844 char* savedPos = cur;
cecfc5e7 1845
d12e3536
VZ
1846 int tmpLnNo;
1847 store_line_no( tmpLnNo );
cecfc5e7
VZ
1848
1849 --cur; // rewind back to ';'
1850
d12e3536
VZ
1851 do
1852 {
1853 spAttribute* pAttr = new spAttribute();
1854 // FOR NOW:: line not is not exact, if member declaration is multiline
1855 pAttr->mSrcLineNo = get_line_no();
cecfc5e7 1856
d12e3536
VZ
1857 mpCurCtx->AddMember( pAttr );
1858 pAttr->mVisibility = mCurVis;
cecfc5e7 1859
d12e3536 1860 pAttr->mIsConstant = 0;
cecfc5e7 1861
d12e3536
VZ
1862 if ( firstMember )
1863 {
1864 firstMember = 0;
d12e3536 1865 }
cecfc5e7 1866
d12e3536 1867 skip_token_back( cur );
cecfc5e7 1868
d12e3536
VZ
1869 // attach comments about the attribute
1870 AttachComments( *pAttr, cur );
cecfc5e7 1871
8bc17f14 1872 pAttr->m_Name = get_token_str( cur );
cecfc5e7 1873
d12e3536
VZ
1874 // guessing that this going to be variable type
1875 skip_next_token_back( cur );
1876 skip_token_back( cur );
1877
821d644d 1878 pAttr->m_Type = get_token_str( cur );
cecfc5e7 1879
d12e3536
VZ
1880 // if comma, than variable list continues
1881 // otherwise the variable type reached - stop
cecfc5e7 1882
fa1af598 1883 if ( *cur == _T('=') )
d12e3536
VZ
1884 {
1885 // yes, we've mistaken, it was not a identifier,
1886 // but it's default value
fa1af598 1887 pAttr->m_InitVal = pAttr->m_Name;
cecfc5e7 1888
d12e3536
VZ
1889 // skip default value and '=' symbol
1890 skip_next_token_back( cur );
1891 skip_token_back( cur );
cecfc5e7 1892
8bc17f14 1893 pAttr->m_Name = get_token_str( cur );
cecfc5e7 1894
d12e3536
VZ
1895 skip_next_token_back( cur );
1896 skip_token_back( cur );
1897 }
cecfc5e7 1898
d12e3536
VZ
1899 if ( *cur != ',' )
1900 {
1901 type = get_token_str( cur );
1902 break;
1903 }
cecfc5e7 1904
d12e3536 1905 } while(1);
cecfc5e7 1906
8ad74db3 1907 size_t first = 0;
cecfc5e7 1908
d12e3536
VZ
1909 // set up types for all collected (same-type) attributes;
1910 while ( first != members.size() - 1 )
1911 {
1912 spAttribute* pAttr = members[first++]->CastToAttribute();
1913 if ( !pAttr )
1914 continue;
cecfc5e7 1915
821d644d
WS
1916 if ( pAttr->m_Type.empty() )
1917 pAttr->m_Type = type;
d12e3536 1918 pAttr->mVisibility = mCurVis;
cecfc5e7 1919
8bc17f14 1920 if ( !pAttr->m_Name.empty() )
821d644d 1921 arrange_indirection_tokens_between( pAttr->m_Type, pAttr->m_Name );
d12e3536 1922 }
cecfc5e7 1923
d12e3536
VZ
1924 cur = savedPos;
1925 restore_line_no( tmpLnNo );
cecfc5e7 1926
d12e3536 1927 clear_commets_queue();
cecfc5e7
VZ
1928
1929
1930}
1931
1932void CJSourceParser::SkipFunction( char*& cur )
1933{
d12e3536
VZ
1934 while ( *cur != '(' && cur < _gSrcEnd )
1935 {
1936 if (*cur == 10 ) ++_gLineNo;
1937 ++cur;
1938 }
cecfc5e7 1939
d12e3536
VZ
1940 skip_next_token_back( cur ); // go back and skip function identifier
1941 skip_token_back( cur ); // go back and skip return type
cecfc5e7 1942
d12e3536 1943 skip_block( cur ); // now, go ahead and skip whole declaration
cecfc5e7 1944
d12e3536 1945 SkipFunctionBody( cur );
cecfc5e7
VZ
1946
1947}
1948
1949void CJSourceParser::SkipFunctionBody( char*& cur )
1950{
d12e3536 1951 // FIXME:: check for comments and quoted stirngs here
cecfc5e7 1952
8ad74db3 1953 bool hasDefinition = false;
cecfc5e7 1954
d12e3536
VZ
1955 while( *cur != '{' && *cur != ';' )
1956 {
1957 if (*cur == 10 ) ++_gLineNo;
1958 ++cur;
1959 }
cecfc5e7 1960
d12e3536
VZ
1961 if ( *cur == ';' )
1962 {
1963 ++cur;
1964 }
1965 else
1966 {
8ad74db3 1967 hasDefinition = true;
cecfc5e7 1968
d12e3536
VZ
1969 skip_scope_block( cur ); // skip the whole imp.
1970 }
cecfc5e7 1971
d12e3536
VZ
1972 if ( mpCurCtx->GetType() == SP_CTX_OPERATION )
1973 {
1974 spOperation& op = *((spOperation*)mpCurCtx);
cecfc5e7 1975
d12e3536 1976 int curOfs = int ( cur - _gSrcStart );
cecfc5e7 1977
d12e3536 1978 op.mContextLength = curOfs - mpCurCtx->mSrcOffset;
cecfc5e7 1979
d12e3536 1980 op.mHasDefinition = hasDefinition;
cecfc5e7 1981
d12e3536 1982 // separate scope resolution token from the name of operation
cecfc5e7 1983
8bc17f14 1984 for( size_t i = 0; i != op.m_Name.length(); ++i )
d12e3536 1985 {
8bc17f14 1986 if ( op.m_Name[i] == ':' && op.m_Name[i+1] == ':' )
d12e3536 1987 {
c69a7d10 1988 wxString unscoped( op.m_Name, i+2, op.m_Name.length() - ( i + 2 ) );
cecfc5e7 1989
c69a7d10 1990 op.mScope = wxString( op.m_Name, 0, i );
cecfc5e7 1991
8bc17f14 1992 op.m_Name = unscoped;
cecfc5e7 1993
d12e3536
VZ
1994 break;
1995 }
1996 }
1997 }
cecfc5e7
VZ
1998}
1999
2000bool CJSourceParser::CheckVisibilty( char*& cur )
2001{
d12e3536
VZ
2002 size_t len = get_token_len( cur );
2003
2004 if ( cmp_tokens_fast( cur, "public:", len ) )
2005 {
2006 mCurVis = SP_VIS_PUBLIC;
8ad74db3 2007 return true;
d12e3536
VZ
2008 }
2009
2010 if ( cmp_tokens_fast( cur, "protected:", len ) )
2011 {
2012 mCurVis = SP_VIS_PROTECTED;
8ad74db3 2013 return true;
d12e3536
VZ
2014 }
2015
2016 if ( cmp_tokens_fast( cur, "private:", len ) )
2017 {
2018 mCurVis = SP_VIS_PRIVATE;
8ad74db3 2019 return true;
d12e3536
VZ
2020 }
2021
8ad74db3 2022 return false;
cecfc5e7
VZ
2023}
2024
2025void CJSourceParser::AddClassNode( char*& cur )
2026{
d12e3536
VZ
2027 char* ctxStart = cur;
2028
2af95167 2029 wxString classkeyword = get_token_str( cur );
d12e3536
VZ
2030
2031 skip_token( cur ); // skip 'class' keyword
2032 if ( !get_next_token( cur ) ) return;
2033
2034 // in C++
2035 if ( *cur == ':' )
2036 {
2037 skip_token( cur );
2038 get_next_token( cur );
2039 }
cecfc5e7 2040
d12e3536
VZ
2041 // by default all class members are private
2042 mCurVis = SP_VIS_PRIVATE;
cecfc5e7 2043
d12e3536
VZ
2044 spClass* pClass = new spClass();
2045 if ( classkeyword == "class" )
2046 pClass->mClassSubType = SP_CLTYPE_CLASS;
2047 else if ( classkeyword == "struct" ) {
2048 pClass->mClassSubType = SP_CLTYPE_STRUCTURE;
cecfc5e7 2049
d12e3536
VZ
2050 mCurVis = SP_VIS_PUBLIC;
2051 }
2052 else if ( classkeyword == "union" ) {
2053 pClass->mClassSubType = SP_CLTYPE_UNION;
cecfc5e7 2054
d12e3536
VZ
2055 mCurVis = SP_VIS_PUBLIC;
2056 }
2057 else if ( classkeyword == "interface" )
2058 pClass->mClassSubType = SP_CLTYPE_INTERFACE;
2059 else {
2060 pClass->mClassSubType = SP_CLTYPE_INVALID;
cecfc5e7 2061
d12e3536
VZ
2062 wxFAIL_MSG("unknown class keyword");
2063 }
cecfc5e7 2064
d12e3536 2065 mpCurCtx->AddMember( pClass );
cecfc5e7 2066
d12e3536
VZ
2067 // attach comments about the class
2068 AttachComments( *pClass, cur );
cecfc5e7 2069
d12e3536 2070 pClass->mSrcLineNo = get_line_no();
cecfc5e7 2071
d12e3536 2072 pClass->mSrcOffset = int( ctxStart - _gSrcStart );
cecfc5e7 2073
d12e3536 2074 char* nameTok = cur;
8bc17f14 2075 pClass->m_Name = get_token_str( cur );
cecfc5e7 2076
d12e3536 2077 bool isDerived = 0;
cecfc5e7 2078
d12e3536 2079 // DANGER-MACROS::
cecfc5e7 2080
d12e3536
VZ
2081 do
2082 {
2083 skip_token( cur );
2084 if ( !get_next_token( cur ) ) return;
cecfc5e7 2085
d12e3536
VZ
2086 if ( *cur == ':' )
2087 {
2088 isDerived = 1;
cecfc5e7 2089
d12e3536 2090 char* tok = cur;
cecfc5e7 2091
d12e3536
VZ
2092 int tmpLn;
2093 store_line_no( tmpLn );
cecfc5e7 2094
d12e3536
VZ
2095 skip_next_token_back( tok );
2096 skip_token_back( tok );
cecfc5e7 2097
d12e3536 2098 restore_line_no( tmpLn );
cecfc5e7 2099
d12e3536
VZ
2100 // class name should precend ':' colon, thus
2101 // the one which was captured before was
2102 // proablty something else (like __dllexport MyClass : ... )
cecfc5e7 2103
d12e3536
VZ
2104 if ( nameTok != tok )
2105 {
8bc17f14 2106 pClass->m_Name = get_token_str( tok );
d12e3536 2107 }
cecfc5e7 2108
d12e3536 2109 }
cecfc5e7 2110
d12e3536
VZ
2111 if ( *cur == '{' )
2112 break;
cecfc5e7 2113
d12e3536
VZ
2114 if ( *cur == ',' )
2115 continue;
cecfc5e7 2116
d12e3536 2117 size_t len = get_token_len( cur );
cecfc5e7 2118
d12e3536
VZ
2119 // skip neglectable C++ modifieres
2120 if ( cmp_tokens_fast( cur, "public", len ) )
2121 continue;
cecfc5e7 2122
d12e3536
VZ
2123 if ( cmp_tokens_fast( cur, "protected", len ) )
2124 continue;
cecfc5e7 2125
d12e3536
VZ
2126 if ( cmp_tokens_fast( cur, "private", len ) )
2127 continue;
cecfc5e7 2128
d12e3536
VZ
2129 if ( cmp_tokens_fast( cur, "virtual", len ) )
2130 continue;
cecfc5e7 2131
d12e3536 2132 // skip neglectable JAVA modifieres
cecfc5e7 2133
d12e3536
VZ
2134 if ( cmp_tokens_fast( cur, "extends", len ) )
2135 {
2136 isDerived = 1;
2137 continue;
2138 }
cecfc5e7 2139
d12e3536
VZ
2140 if ( cmp_tokens_fast( cur, "implements", len ) )
2141 {
2142 isDerived = 1;
2143 continue;
2144 }
cecfc5e7 2145
d12e3536 2146 // all we need to know is superclass or interface
cecfc5e7 2147
d12e3536
VZ
2148 char* tok = cur;
2149 int tmpLn;
2150 store_line_no( tmpLn );
cecfc5e7 2151
d12e3536
VZ
2152 skip_token(tok);
2153 get_next_token(tok);
cecfc5e7 2154
d12e3536 2155 restore_line_no( tmpLn );
cecfc5e7 2156
d12e3536 2157 if ( *tok != ':' && *cur != ':' )
cecfc5e7 2158
2af95167 2159 pClass->m_SuperClassNames.push_back( wxString( cur, len ) );
cecfc5e7 2160
d12e3536 2161 } while(1);
cecfc5e7 2162
d12e3536
VZ
2163 if ( !isDerived )
2164 {
2165 int tmpLn;
2166 store_line_no( tmpLn );
2167
33882d15 2168 while ( pClass->m_SuperClassNames.size() )
d12e3536 2169
33882d15 2170 pClass->m_SuperClassNames.erase( &pClass->m_SuperClassNames[0] );
cecfc5e7 2171
d12e3536 2172 char* tok = cur;
cecfc5e7 2173
d12e3536
VZ
2174 // some non-obviouse token was following "class" keyword -
2175 // we've confused it with class name - thus now we're reverting this mistake
cecfc5e7 2176
d12e3536
VZ
2177 skip_next_token_back( tok );
2178 skip_token_back( tok );
cecfc5e7 2179
8bc17f14 2180 pClass->m_Name = get_token_str( tok );
cecfc5e7 2181
d12e3536
VZ
2182 restore_line_no( tmpLn );
2183 }
cecfc5e7
VZ
2184
2185
d12e3536 2186 ++cur; // skip opening curly brace
cecfc5e7 2187
d12e3536 2188 pClass->mHeaderLength = ( cur - ctxStart );
cecfc5e7 2189
d12e3536
VZ
2190 // now, enter the class context
2191 mpCurCtx = pClass;
cecfc5e7 2192
d12e3536 2193 clear_commets_queue();
cecfc5e7
VZ
2194}
2195
41964404 2196void CJSourceParser::AddEnumNode( wxChar*& cur )
cecfc5e7 2197{
d12e3536 2198 // now the cursor is at "enum" keyword
41964404 2199 wxChar* start = cur;
d12e3536
VZ
2200
2201 spEnumeration* pEnum = new spEnumeration();
2202 mpCurCtx->AddMember( pEnum );
cecfc5e7 2203
d12e3536 2204 pEnum->mSrcLineNo = get_line_no();
cecfc5e7 2205
cecfc5e7 2206
d12e3536 2207 AttachComments( *pEnum, cur );
cecfc5e7 2208
d12e3536
VZ
2209 skip_token( cur );
2210 if ( !get_next_token( cur ) ) return;
cecfc5e7 2211
d12e3536
VZ
2212 // check if enumeration has got it's identifier
2213 if ( *cur != '{' )
2214 {
8bc17f14 2215 pEnum->m_Name = get_token_str( cur );
d12e3536 2216 }
cecfc5e7 2217
d12e3536 2218 if ( !skip_imp_block( cur ) ) return;
cecfc5e7 2219
c69a7d10 2220 get_string_between( start, cur, &pEnum->m_EnumContent );
cecfc5e7 2221
d12e3536
VZ
2222 if ( get_next_token(cur) )
2223 {
2224 // check if the identifier if after the {...} block
2225 if ( *cur != ';' )
cecfc5e7 2226
8bc17f14 2227 pEnum->m_Name = get_token_str( cur );
d12e3536 2228 }
cecfc5e7 2229
d12e3536 2230 clear_commets_queue();
cecfc5e7
VZ
2231}
2232
41964404 2233void CJSourceParser::AddTypeDefNode( wxChar*& cur )
cecfc5e7 2234{
d12e3536 2235 // now the cursor at the token next to "typedef" keyword
cecfc5e7 2236
d12e3536 2237 if ( !get_next_token(cur) ) return;
cecfc5e7 2238
41964404 2239 wxChar* start = cur;
cecfc5e7 2240
d12e3536
VZ
2241 spTypeDef* pTDef = new spTypeDef();
2242 mpCurCtx->AddMember( pTDef );
cecfc5e7 2243
d12e3536 2244 pTDef->mSrcLineNo = get_line_no();
cecfc5e7 2245
d12e3536 2246 AttachComments( *pTDef, cur );
cecfc5e7 2247
d12e3536 2248 skip_statement( cur );
cecfc5e7 2249
d12e3536
VZ
2250 int tmpLnNo;
2251 store_line_no( tmpLnNo );
cecfc5e7 2252
41964404 2253 wxChar* tok = cur-1;
d12e3536 2254 skip_next_token_back( tok );
cecfc5e7 2255
41964404 2256 wxChar* nameEnd = tok;
cecfc5e7 2257
d12e3536 2258 skip_token_back( tok );
cecfc5e7 2259
41964404 2260 wxChar* nameStart = tok;
cecfc5e7 2261
d12e3536 2262 skip_next_token_back( tok );
cecfc5e7 2263
41964404 2264 wxChar* typeEnd = tok;
cecfc5e7 2265
d12e3536
VZ
2266 // check if it's function prototype
2267 if ( *nameStart == ')' )
2268 {
2269 typeEnd = nameStart+1;
2270
2271 // skip argument list
2272 while ( *nameStart != '(' ) --nameStart;
cecfc5e7 2273
d12e3536
VZ
2274 // skip to function type definition
2275 while ( *nameStart != ')' ) --nameStart;
cecfc5e7 2276
d12e3536 2277 skip_next_token_back( nameStart );
cecfc5e7 2278
d12e3536 2279 nameEnd = nameStart;
cecfc5e7 2280
d12e3536 2281 skip_token_back( nameStart );
cecfc5e7 2282
d12e3536
VZ
2283 if ( *nameStart == '*' ) ++nameStart;
2284 }
cecfc5e7 2285
c69a7d10 2286 get_string_between( start, typeEnd, &pTDef->m_OriginalType );
cecfc5e7 2287
8bc17f14 2288 get_string_between( nameStart, nameEnd, &pTDef->m_Name );
cecfc5e7 2289
d12e3536 2290 clear_commets_queue();
cecfc5e7 2291
d12e3536 2292 restore_line_no( tmpLnNo );
cecfc5e7 2293}