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