X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cecfc5e7e54067ea099334a1fbce852ca69a6b11..90f3fe56ee58fec86d7f938f9c630c0745f0a2dc:/utils/HelpGen/src/cjparser.cpp diff --git a/utils/HelpGen/src/cjparser.cpp b/utils/HelpGen/src/cjparser.cpp index 9c90e37862..1d87c02449 100644 --- a/utils/HelpGen/src/cjparser.cpp +++ b/utils/HelpGen/src/cjparser.cpp @@ -6,12 +6,11 @@ // Created: 22/09/98 // RCS-ID: $Id$ // Copyright: (c) Aleskandars Gluchovas -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ -#pragma implementation "acell.h" -#pragma interface +# pragma implementation "acell.h" #endif // For compilers that support precompilation, includes "wx/wx.h". @@ -29,11 +28,11 @@ #if defined( wxUSE_TEMPLATE_STL ) - #include + #include #else - #include "wxstlac.h" + #include "wxstlac.h" #endif @@ -53,23 +52,23 @@ static int _gCQSize = 0; /***** keyword map related structures *****/ -struct less_c_str +struct less_c_str { - inline bool operator()( char* x, char* y) const - { return ( strcmp( x,y ) < 0 ); - } + inline bool operator()( char* x, char* y) const + { return ( strcmp( x,y ) < 0 ); + } }; //WXSTL_MAP(CharPtrT,CharPtrT, LESS_THEN_FUNCTOR(CharPtrT)); #if defined( wxUSE_TEMPLATE_STL ) - typedef map< char*, char*, less_c_str > KeywordMapT; + typedef map< char*, char*, less_c_str > KeywordMapT; #else - typedef char* CharPtrT; - typedef WXSTL_MAP( CharPtrT, CharPtrT ,less_c_str) KeywordMapT; + typedef char* CharPtrT; + typedef WXSTL_MAP( CharPtrT, CharPtrT ,less_c_str) KeywordMapT; #endif @@ -78,282 +77,282 @@ static int __gMapReady = 0; static char* __gKeyWords[] = { - "public", - "protected", - "private", - - "class", - "struct", - "union", - "enum", - "interface", - - "package", - "import", - - "typedef", - "template", - "friend", - "const", - "volatile", - "mutable", - "virtual", - "inline", - "static", - "register", - - "final", - "abstract", - "native", - - "__stdcall", - "extern", - - 0 + "public", + "protected", + "private", + + "class", + "struct", + "union", + "enum", + "interface", + + "package", + "import", + + "typedef", + "template", + "friend", + "const", + "volatile", + "mutable", + "virtual", + "inline", + "static", + "register", + + "final", + "abstract", + "native", + + "__stdcall", + "extern", + + 0 }; static void check_keyword_map() { - if ( !__gMapReady ) - { - __gMapReady = 1; + if ( !__gMapReady ) + { + __gMapReady = 1; - // "make sure" the address of the first member of non-polimorphic class - // coinsides with the address of the instance + // "make sure" the address of the first member of non-polimorphic class + // coinsides with the address of the instance - char** keyword = __gKeyWords; + char** keyword = __gKeyWords; - while ( (*keyword) != 0 ) - { - __gMultiLangMap.insert( - KeywordMapT::value_type( *keyword, *keyword ) - ); + while ( (*keyword) != 0 ) + { + __gMultiLangMap.insert( + KeywordMapT::value_type( *keyword, *keyword ) + ); - ++keyword; - } - } + ++keyword; + } + } } /***** helper functions *****/ static inline void skip_to_eol( char*& cur ) { - while( *(cur) != 10 && *cur != 13 && cur < _gSrcEnd) ++cur; + while( *(cur) != 10 && *cur != 13 && cur < _gSrcEnd) ++cur; } static inline void skip_eol( char*& cur ) { - if ( *cur == 13 ) + if ( *cur == 13 ) - cur += 2; - else - cur += 1; + cur += 2; + else + cur += 1; - ++_gLineNo; + ++_gLineNo; } static inline bool skip_to_next_comment_in_the_line( char*& cur ) { - do - { - while( cur < _gSrcEnd && - *cur != 10 && - *cur != 13 && - *cur != '/' - ) ++cur; - - if ( cur == _gSrcEnd ) return FALSE; - - if ( *cur == '/' ) - { - if ( (*(cur+1) == '*') || - (*(cur+1) == '/') ) return TRUE; - else - { - ++cur; - continue; - } - } - - return FALSE; - - } while(1); + do + { + while( cur < _gSrcEnd && + *cur != 10 && + *cur != 13 && + *cur != '/' + ) ++cur; + + if ( cur == _gSrcEnd ) return FALSE; + + if ( *cur == '/' ) + { + if ( (*(cur+1) == '*') || + (*(cur+1) == '/') ) return TRUE; + else + { + ++cur; + continue; + } + } + + return FALSE; + + } while(1); } inline static void store_line_no( int& toVar ) { - toVar = _gLineNo; + toVar = _gLineNo; } inline static void restore_line_no( int storedLineNo ) { - _gLineNo = storedLineNo; + _gLineNo = storedLineNo; } inline static int get_line_no() { - return _gLineNo; + return _gLineNo; } static void skip_to_prev_line( char*& cur ) { - while( cur >= _gSrcStart && - *cur != 10 && - *cur != 13 - ) --cur; + while( cur >= _gSrcStart && + *cur != 10 && + *cur != 13 + ) --cur; - // NOTE:: '\n' is 13,10 for DOS - // '\n' is 10 for UNIX + // NOTE:: '\n' is 13,10 for DOS + // '\n' is 10 for UNIX - // NOTE1: '\n' symbol is not used here, - // to provide possibility of loading - // file as binary + // NOTE1: '\n' symbol is not used here, + // to provide possibility of loading + // file as binary - --cur; - if ( *cur == 10 ) - { - ++cur; - return; - } + --cur; + if ( *cur == 10 ) + { + ++cur; + return; + } - if ( *cur == 13 ) --cur; + if ( *cur == 13 ) --cur; - while( cur >= _gSrcStart && - *cur != 10 && - *cur != 13 - ) --cur; + while( cur >= _gSrcStart && + *cur != 10 && + *cur != 13 + ) --cur; - ++cur; // move to the first character in the line + ++cur; // move to the first character in the line } static inline void skip_comments( char*& cur ) { - ++cur; // skip '/' token + ++cur; // skip '/' token - if ( *cur != '/' && *cur != '*' ) return; + if ( *cur != '/' && *cur != '*' ) return; - // first, store position of the comment into the queue - // (which further will be attached to the next context - // found) + // first, store position of the comment into the queue + // (which further will be attached to the next context + // found) - if ( cur-1 != _gLastSuppresedComment ) - { - if ( _gCQSize == MAX_CQ_ENTRIES ) - { - size_t i = MAX_CQ_ENTRIES-1; + if ( cur-1 != _gLastSuppresedComment ) + { + if ( _gCQSize == MAX_CQ_ENTRIES ) + { + size_t i = MAX_CQ_ENTRIES-1; - while( i != 0 ) - { - _gCommentsQueue[i-1] = _gCommentsQueue[i]; - --i; - } + while( i != 0 ) + { + _gCommentsQueue[i-1] = _gCommentsQueue[i]; + --i; + } - --_gCQSize ; - } + --_gCQSize ; + } - _gCommentsQueue[_gCQSize++] = cur-1; - } + _gCommentsQueue[_gCQSize++] = cur-1; + } - // if signle-line comment, skip it now - if ( *cur == '/' ) - { - skip_to_eol( cur ); - skip_eol( cur ); - return; - } + // if signle-line comment, skip it now + if ( *cur == '/' ) + { + skip_to_eol( cur ); + skip_eol( cur ); + return; + } - size_t level = 1; + size_t level = 1; - // check for multiline comment (handle nested multiline comments!) + // check for multiline comment (handle nested multiline comments!) - int line_len = 0; + int line_len = 0; - ++cur; - ++cur; - do - { - // TBD:: check eof cond. + ++cur; + ++cur; + do + { + // TBD:: check eof cond. - // detect and remove vertical columns of '*''s + // detect and remove vertical columns of '*''s - while ( *cur != '/' && cur < _gSrcEnd ) - { - switch (*cur) - { - case '*' : - { - if ( *(cur+1) != '/' ) - { - if ( line_len == 1 ) + while ( *cur != '/' && cur < _gSrcEnd ) + { + switch (*cur) + { + case '*' : + { + if ( *(cur+1) != '/' ) + { + if ( line_len == 1 ) - *cur = ' '; - } + *cur = ' '; + } - break; - } + break; + } - case 13 : line_len = 0; break; - case 10 : { line_len = 0; ++_gLineNo; } break; + case 13 : line_len = 0; break; + case 10 : { line_len = 0; ++_gLineNo; } break; - default : ++line_len; - } + default : ++line_len; + } - ++cur; - } + ++cur; + } - if ( cur >= _gSrcEnd ) return; + if ( cur >= _gSrcEnd ) return; - ++cur; + ++cur; - if ( *(cur-2) == '*' ) - { - --level; - if ( level == 0 ) - break; - } - else - if ( *cur == '*' ) - { - ++cur; - ++cur; + if ( *(cur-2) == '*' ) + { + --level; + if ( level == 0 ) + break; + } + else + if ( *cur == '*' ) + { + ++cur; + ++cur; - ++level; - } + ++level; + } - } while(1); + } while(1); } static inline void clear_commets_queue() { - _gCQSize = 0; + _gCQSize = 0; } static inline void skip_quoted_string( char*& cur ) { - ++cur; // skip first quote '"' + ++cur; // skip first quote '"' - // check if quote wasn't prefixed - if ( *(cur-2) == '\\' ) - return; + // check if quote wasn't prefixed + if ( *(cur-2) == '\\' ) + return; - do - { - while ( *cur != '"' && cur < _gSrcEnd ) - { - if ( *cur == 10 ) ++_gLineNo; - ++cur; - } + do + { + while ( *cur != '"' && cur < _gSrcEnd ) + { + if ( *cur == 10 ) ++_gLineNo; + ++cur; + } - if ( cur >= _gSrcEnd ) return; + if ( cur >= _gSrcEnd ) return; - ++cur; // skip the last quote + ++cur; // skip the last quote - // check if it wasn't prefixed + // check if it wasn't prefixed - if ( *(cur-2) != '\\' ) - break; + if ( *(cur-2) != '\\' ) + break; - } while (1); + } while (1); } // skips subsequent white space and comments @@ -361,283 +360,294 @@ static inline void skip_quoted_string( char*& cur ) static inline bool get_next_token( char*& cur ) { - for( ; cur < _gSrcEnd; ++cur ) - { - switch( *(cur) ) - { - case ' ' : continue; - case '\t': continue; - case 13 : continue; - - case 10 : { ++_gLineNo;continue; } - - case '/' : skip_comments( cur ); - --cur; - continue; - - default : break; - }; - - break; - } - - if ( cur >= _gSrcEnd ) - - return FALSE; - else - return TRUE; + for( ; cur < _gSrcEnd; ++cur ) + { + switch( *(cur) ) + { + case ' ' : continue; + case '\t': continue; + case 13 : continue; + + case 10 : { ++_gLineNo;continue; } + + case '/' : skip_comments( cur ); + --cur; + continue; + + default : break; + }; + + break; + } + + if ( cur >= _gSrcEnd ) + + return FALSE; + else + return TRUE; } static inline void skip_preprocessor_dir( char*& cur ) { - do - { - skip_to_eol(cur); + do + { + skip_to_eol(cur); - if ( *(cur-1) != '\\' ) - break; + if ( *(cur-1) != '\\' ) + break; - if ( cur < _gSrcEnd ) - skip_eol( cur ); - else - break; + if ( cur < _gSrcEnd ) + skip_eol( cur ); + else + break; - } while(1); + } while(1); } static void skip_token( char*& cur ) { - if ( *cur == '"' ) - { - skip_quoted_string( cur ); - return; - } - - if ( *cur == ',' || - *cur == ';' || - *cur == '<' || - *cur == '>' || - *cur == '=' || - *cur == ')' || - *cur == '(' - ) - { - ++cur; - return; - } - - ++cur; // leading character is always skipped - - for( ; cur < _gSrcEnd ; ++cur ) - { - switch ( *cur ) - { - case ' ' : break; - case '\t': break; - case 13 : break; - case 10 : break; - case ',' : break; - case ';' : break; - case '<' : break; - case '>' : break; - - // FIXME:: QUICK-HACK:: to treat scope resolution - // tokens are a part of the string - e.g. SomeSpace::SubName would - // become one token - - case ':' : if ( *(cur+1) == ':' ) - { - ++cur; - continue; - } - - break; - case '=' : break; - case '(' : break; - case ')' : break; - case '{' : break; - case '}' : break; - - default : continue; - }; - break; - } + if ( *cur == '"' ) + { + skip_quoted_string( cur ); + return; + } + + if ( *cur == ',' || + *cur == ';' || + *cur == ')' || + *cur == '(' + ) + { + ++cur; + return; + } + + // special case of "!=", "<=", ... 2 character composite tokens + if ( *cur == '<' || + *cur == '>' || + *cur == '=' || + *cur == '!' + ) + { + cur++; + if ( *cur == '=' ) + cur++; + + return; + } + + ++cur; // leading character is always skipped + + for( ; cur < _gSrcEnd ; ++cur ) + { + switch ( *cur ) + { + case ' ' : break; + case '\t': break; + case 13 : break; + case 10 : break; + case ',' : break; + case ';' : break; + case '<' : break; + case '>' : break; + + // FIXME:: QUICK-HACK:: to treat scope resolution + // tokens are a part of the string - e.g. SomeSpace::SubName would + // become one token + + case ':' : if ( *(cur+1) == ':' ) + { + ++cur; + continue; + } + + break; + case '=' : break; + case '(' : break; + case ')' : break; + case '{' : break; + case '}' : break; + + default : continue; + }; + break; + } } static inline size_t get_token_len( char* tok ) { - char* start = tok; + char* start = tok; - skip_token( tok ); + skip_token( tok ); - return size_t( tok - start ); + return size_t( tok - start ); } // returns true, if given tokens are equel static inline bool cmp_tokens( char* tok1, char* tok2 ) { - // NOTE:: the case one token includes - // other in it's entirely is not handled + // NOTE:: the case one token includes + // other in it's entirely is not handled - size_t len = get_token_len( tok1 ); + size_t len = get_token_len( tok1 ); - // assuming that tokens are non-zero length + // assuming that tokens are non-zero length - do - { - if ( *(tok1++) != *(tok2++) ) - return FALSE; + do + { + if ( *(tok1++) != *(tok2++) ) + return FALSE; - --len; + --len; - } while ( --len ); + } while ( --len ); - return TRUE; + return TRUE; } static inline bool cmp_tokens_fast( char* tok1, char* tok2, size_t len ) { - do - { - if ( *(tok1++) != *(tok2++) ) - return FALSE; + do + { + if ( *(tok1++) != *(tok2++) ) + return FALSE; - } while ( --len ); + } while ( --len ); - return TRUE; + return TRUE; } static inline void skip_tempalate_statement( char*& cur ) { - size_t level = 0; + size_t level = 0; - // go one level deeper - while( *cur != '<' && cur < _gSrcEnd ) - { - if (*cur == 10 ) ++_gLineNo; - ++cur; - } + // go one level deeper + while( *cur != '<' && cur < _gSrcEnd ) + { + if (*cur == 10 ) ++_gLineNo; + ++cur; + } - // FIXME:: template should be checked statement for - // comments inside of it + // FIXME:: template should be checked statement for + // comments inside of it - do - { - if ( *cur == '<' ) - ++level; - else - --level; + do + { + if ( *cur == '<' ) + ++level; + else + --level; - ++cur; // skip '<' or '>' token + ++cur; // skip '<' or '>' token - if ( level == 0 ) - return; + if ( level == 0 ) + return; - while( *cur != '<' && *cur != '>' && cur < _gSrcEnd ) - { - if (*cur == 10 ) ++_gLineNo; - ++cur; - } + while( *cur != '<' && *cur != '>' && cur < _gSrcEnd ) + { + if (*cur == 10 ) ++_gLineNo; + ++cur; + } - } while (1); + } while (1); } static inline void skip_statement( char*& cur ) { - for( ; cur < _gSrcEnd; ++cur ) + for( ; cur < _gSrcEnd; ++cur ) - switch (*cur) - { - case ';' : ++cur; // skip statement-terminator token - return; + switch (*cur) + { + case ';' : ++cur; // skip statement-terminator token + return; - case '"' : skip_quoted_string(cur); - --cur; - continue; + case '"' : skip_quoted_string(cur); + --cur; + continue; - case 10 : ++_gLineNo; + case 10 : ++_gLineNo; - continue; - case '/' : skip_comments( cur ); - --cur; - continue; - default : continue; - } + continue; + case '/' : skip_comments( cur ); + --cur; + continue; + default : continue; + } } // "reversed" versions of skip_token() and get_next_token() static inline void skip_token_back( char*& cur ) { - // FIXME:: now, when moving backwards, neither strings nor - // comment blocks are checked + // FIXME:: now, when moving backwards, neither strings nor + // comment blocks are checked - --cur; // skip to the trailing character + --cur; // skip to the trailing character - if ( *cur == ',' || - *cur == ')' || - *cur == '(' - ) - return; + if ( *cur == ',' || + *cur == ')' || + *cur == '(' + ) + return; - for( ; cur < _gSrcEnd ; --cur ) - { - switch ( *cur ) - { - case ' ' : break; - case '\t': break; - case 13 : break; - case 10 : break; - case ',' : break; - case '(' : break; + for( ; cur < _gSrcEnd ; --cur ) + { + switch ( *cur ) + { + case ' ' : break; + case '\t': break; + case 13 : break; + case 10 : break; + case ',' : break; + case '(' : break; - default : continue; - }; + default : continue; + }; - break; - } + break; + } - ++cur; // get to the leading character of the token + ++cur; // get to the leading character of the token } static inline void skip_next_token_back( char*& cur ) { - --cur; // skip leading character of the current token - - if ( *cur == ',' || - *cur == ')' || - *cur == '(' - ) - { - ++cur; - return; - } - - for( ; cur < _gSrcEnd; --cur ) - { - switch ( *cur ) - { - case ' ' : continue; - case '\t': continue; - case 13 : continue; - case 10 : continue; - case ',' : continue; - case '(' : continue; - - default : break; - }; - - break; - } - - ++cur; // position after the trailing charcter of the prev token + --cur; // skip leading character of the current token + + if ( *cur == ',' || + *cur == ')' || + *cur == '(' + ) + { + ++cur; + return; + } + + for( ; cur < _gSrcEnd; --cur ) + { + switch ( *cur ) + { + case ' ' : continue; + case '\t': continue; + case 13 : continue; + case 10 : continue; + case ',' : continue; + case '(' : continue; + + default : break; + }; + + break; + } + + ++cur; // position after the trailing charcter of the prev token } static string get_token_str( char* cur ) { - return string( cur, get_token_len( cur ) ); + return string( cur, get_token_len( cur ) ); } // skips token or whole expression which may have @@ -649,260 +659,260 @@ static string get_token_str( char* cur ) static size_t skip_block( char*& cur ) { - size_t level = 0; // nesting level - - char* start = cur; - - // NOTE:: assumed that block not necessarely starts - // with bracket rightaway - - if ( *cur == '(' ) - { - ++level; - } - - do - { - skip_token( cur ); - - char* savedPos = cur; - int tmpLnNo; - store_line_no( tmpLnNo ); - - get_next_token( cur ); - - if ( cur >= _gSrcEnd ) return 0; - - if ( *cur == '(' ) - { - ++level; - } - else - if ( *cur == ')' ) - { - if ( level == 0 ) - { - cur = savedPos; - restore_line_no( tmpLnNo ); - - return size_t(cur-start); - } - - --level; - - if ( level == 0 ) - { - ++cur; - - // QUICK-HACK::to easily handle function prototypes , - // it works, besause theoretically there should - // be no cast-expressions in non-implementation - // scope (e.g. "time( (long*)(ptr+1) )" should not - // appear in the declarations, thus it is most likelly - // for the ")(" fragment to be within a function - // prototype in the declarations scope - - if ( *cur == '(' ) - { - ++level; - continue; - } - - else return size_t(cur-start); - } - } - else - { - if ( level == 0 ) - { - cur = savedPos; - restore_line_no( tmpLnNo ); - - return size_t(cur-start); - } - } - - } while(1); + size_t level = 0; // nesting level + + char* start = cur; + + // NOTE:: assumed that block not necessarely starts + // with bracket rightaway + + if ( *cur == '(' ) + { + ++level; + } + + do + { + skip_token( cur ); + + char* savedPos = cur; + int tmpLnNo; + store_line_no( tmpLnNo ); + + get_next_token( cur ); + + if ( cur >= _gSrcEnd ) return 0; + + if ( *cur == '(' ) + { + ++level; + } + else + if ( *cur == ')' ) + { + if ( level == 0 ) + { + cur = savedPos; + restore_line_no( tmpLnNo ); + + return size_t(cur-start); + } + + --level; + + if ( level == 0 ) + { + ++cur; + + // QUICK-HACK::to easily handle function prototypes , + // it works, besause theoretically there should + // be no cast-expressions in non-implementation + // scope (e.g. "time( (long*)(ptr+1) )" should not + // appear in the declarations, thus it is most likelly + // for the ")(" fragment to be within a function + // prototype in the declarations scope + + if ( *cur == '(' ) + { + ++level; + continue; + } + + else return size_t(cur-start); + } + } + else + { + if ( level == 0 ) + { + cur = savedPos; + restore_line_no( tmpLnNo ); + + return size_t(cur-start); + } + } + + } while(1); } // returns 0, if end of source reached static inline bool skip_imp_block( char*& cur ) { - while( *cur != '{' && cur < _gSrcEnd ) - { - skip_token( cur ); - if ( !get_next_token( cur ) ) return FALSE; - } + while( *cur != '{' && cur < _gSrcEnd ) + { + skip_token( cur ); + if ( !get_next_token( cur ) ) return FALSE; + } - while( *cur != '}' && cur < _gSrcEnd ) - { - skip_token( cur ); - if ( !get_next_token( cur ) ) return FALSE; - } + while( *cur != '}' && cur < _gSrcEnd ) + { + skip_token( cur ); + if ( !get_next_token( cur ) ) return FALSE; + } - ++cur; + ++cur; - return TRUE; + return TRUE; } static bool is_class_token( char*& cur ) { - // FIXME:: the below mess should be cleaned in it's entirely + // FIXME:: the below mess should be cleaned in it's entirely - if ( *cur == 'i' ) - if ( *(cur+1) == 'n' ) + if ( *cur == 'i' ) + if ( *(cur+1) == 'n' ) - return cmp_tokens_fast( cur, "interface", 9 ); + return cmp_tokens_fast( cur, "interface", 9 ); - if ( *cur == 'c' ) - if ( *(cur+1) == 'l' ) + if ( *cur == 'c' ) + if ( *(cur+1) == 'l' ) - return cmp_tokens_fast( cur, "class", 5 ); + return cmp_tokens_fast( cur, "class", 5 ); - if ( *cur == 's' ) - if ( *(cur+1) == 't' ) + if ( *cur == 's' ) + if ( *(cur+1) == 't' ) - return cmp_tokens_fast( cur, "struct", 6 ); + return cmp_tokens_fast( cur, "struct", 6 ); - if ( *cur == 'u' ) - if ( *(cur+1) == 'n' ) + if ( *cur == 'u' ) + if ( *(cur+1) == 'n' ) - return cmp_tokens_fast( cur, "union", 5 ); + return cmp_tokens_fast( cur, "union", 5 ); - return FALSE; + return FALSE; } inline static bool is_forward_decl( char* cur ) { - do - { - switch( *cur ) - { - case ':' : return FALSE; - case '{' : return FALSE; - case '(' : return FALSE; + do + { + switch( *cur ) + { + case ':' : return FALSE; + case '{' : return FALSE; + case '(' : return FALSE; - case ';' : return TRUE; + case ';' : return TRUE; - default : break; - }; + default : break; + }; - ++cur; + ++cur; - } while (cur < _gSrcEnd); // prevent running out of bounds + } while (cur < _gSrcEnd); // prevent running out of bounds - return FALSE; + return FALSE; } inline static bool is_function( char* cur, bool& isAMacro ) { - isAMacro = FALSE; + isAMacro = FALSE; - int tmpLnNo; - store_line_no( tmpLnNo ); + int tmpLnNo; + store_line_no( tmpLnNo ); - // NOTE:: comments and quoted strings are not checked here + // NOTE:: comments and quoted strings are not checked here - // first,check for "single-line hanginging macros" like: - // ___UNICODE - // + // first,check for "single-line hanginging macros" like: + // ___UNICODE + // - char* eol = cur; - skip_to_eol( eol ); + char* eol = cur; + skip_to_eol( eol ); - skip_token( cur ); - get_next_token( cur ); + skip_token( cur ); + get_next_token( cur ); - if ( cur > eol ) - { - isAMacro = TRUE; - restore_line_no( tmpLnNo ); + if ( cur > eol ) + { + isAMacro = TRUE; + restore_line_no( tmpLnNo ); - return TRUE; - } + return TRUE; + } - // it's not a macro, go to the begining of arg. list - - do - { - // if bracket found, it's a function or a begining - // of some macro - if ( *cur == '(' ) - { - restore_line_no( tmpLnNo ); - return TRUE; - } + // it's not a macro, go to the begining of arg. list - // end of statement found without any brackets in it - // - it cannot be a function + do + { + // if bracket found, it's a function or a begining + // of some macro + if ( *cur == '(' ) + { + restore_line_no( tmpLnNo ); + return TRUE; + } - if ( *cur == ';' ) - { - restore_line_no( tmpLnNo ); - return FALSE; - } + // end of statement found without any brackets in it + // - it cannot be a function - ++cur; + if ( *cur == ';' ) + { + restore_line_no( tmpLnNo ); + return FALSE; + } - } while( cur < _gSrcEnd); + ++cur; - isAMacro = 1; - restore_line_no( tmpLnNo ); + } while( cur < _gSrcEnd); - return FALSE; + isAMacro = 1; + restore_line_no( tmpLnNo ); + + return FALSE; } // upon return the cursor is positioned after the -// terminating curly brace +// terminating curly brace static inline void skip_scope_block( char*& cur ) { - size_t level = 0; + size_t level = 0; - for( ; cur < _gSrcEnd ; ++cur ) + for( ; cur < _gSrcEnd ; ++cur ) - switch( *cur ) - { - case '/' : skip_comments( cur ); - --cur; - continue; - case '"' : skip_quoted_string( cur ); - --cur; - continue; + switch( *cur ) + { + case '/' : skip_comments( cur ); + --cur; + continue; + case '"' : skip_quoted_string( cur ); + --cur; + continue; - case '{' : ++level; - continue; + case '{' : ++level; + continue; - case '}' :--level; - if ( level == 0 ) - { - ++cur; // skip final closing curly brace - return; - } + case '}' :--level; + if ( level == 0 ) + { + ++cur; // skip final closing curly brace + return; + } - case 10 : ++_gLineNo; continue; + case 10 : ++_gLineNo; continue; - default : continue; - }; + default : continue; + }; } // moves tokens like '*' '**', '***', '&' from the name // to the type static void arrange_indirection_tokens_between( string& type, - string& identifier ) + string& identifier ) { - // TBD:: FIXME:: return value of operators ! + // TBD:: FIXME:: return value of operators ! - while ( identifier[0] == '*' || - identifier[0] == '&' - ) - { - type += identifier[0]; - identifier.erase(0,1); + while ( identifier[0] == '*' || + identifier[0] == '&' + ) + { + type += identifier[0]; + identifier.erase(0,1); - if ( !identifier.length() ) return; - } + if ( !identifier.length() ) return; + } } @@ -910,1264 +920,1374 @@ static void arrange_indirection_tokens_between( string& type, static bool is_keyword( char* cur ) { - size_t len = get_token_len( cur ); + size_t len = get_token_len( cur ); + + // put a terminating zero after the given token + char tmp = *(cur + len); + *(cur+len) = '\0'; - // put a terminating zero after the given token - char tmp = *(cur + len); - *(cur+len) = '\0'; + KeywordMapT::iterator i; - KeywordMapT::iterator i; + i = __gMultiLangMap.find( cur ); - i = __gMultiLangMap.find( cur ); - - // restore original character suppresed by terminating zero - *(cur + len) = tmp; - - return ( i != __gMultiLangMap.end() ); + // restore original character suppresed by terminating zero + *(cur + len) = tmp; + + return i == __gMultiLangMap.end() ? false : true; } -static inline void get_string_between( char* start, char* end, - string* pStr ) +static inline void get_string_between( char* start, char* end, + string* pStr ) { - char saved = *end; + char saved = *end; - *end = '\0'; - *pStr = start; - *end = saved; + *end = '\0'; + *pStr = start; + *end = saved; } static char* set_comment_text( string& text, char* start ) { - char* end = start; + char* end = start; - // to avoid poluting the queue with this comment - _gLastSuppresedComment = start; + // to avoid poluting the queue with this comment + _gLastSuppresedComment = start; - skip_comments( end ); + skip_comments( end ); - if ( *(end-1) == '/' ) - end -= 2; + if ( *(end-1) == '/' ) + end -= 2; - start += 2; + start += 2; - // skip multiple leading '/''s or '*''s - while( *start == '/' && start < end ) ++start; - while( *start == '*' && start < end ) ++start; + // skip multiple leading '/''s or '*''s + while( *start == '/' && start < end ) ++start; + while( *start == '*' && start < end ) ++start; - get_string_between( start, end, &text ); + get_string_between( start, end, &text ); - return end; + return end; } /***** Implementation for class CJSourceParser *****/ CJSourceParser::CJSourceParser( bool collectCommnets, bool collectMacros ) - : mpStart(0), - mpEnd(0), - mpCurCtx( 0 ), - mCommentsOn( collectCommnets ), - mMacrosOn ( collectMacros ) + : mpStart(0), + mpEnd(0), + mpCurCtx( 0 ), + mCommentsOn( collectCommnets ), + mMacrosOn ( collectMacros ) { - check_keyword_map(); + check_keyword_map(); } spFile* CJSourceParser::Parse( char* start, char* end ) { - // set up state variables - mCurVis = SP_VIS_PRIVATE; - - spFile* pTopCtx = new spFile(); - mpCurCtx = pTopCtx; - - mIsVirtaul = 0; - mIsTemplate = 0; - mNestingLevel = 0; - - cur = start; - - mpStart = start; - mpEnd = end; - - _gSrcEnd = mpEnd; // let all the C-functions "smell" the end of file - _gSrcStart = start; - - _gLineNo = 0; - - clear_commets_queue(); - - // main parsing loop - - do - { - if ( !get_next_token( cur ) ) - // end of source reached - return pTopCtx; - - if ( memcmp( cur, "ScriptSection( const string&", - strlen( "ScriptSection( const string&" ) - ) == 0 - ) - { - int o; - ++o; - } - - switch (*cur) - { - case '#' : - { - AddMacroNode( cur ); - continue; - } - - case ':' : - { - skip_token( cur ); - continue; - } - - case ';' : - { - skip_token( cur ); - continue; - } - - case ')' : - { - skip_token( cur ); - continue; - } - - case '=' : - { - skip_token( cur ); - continue; - } - - default: break; - } - - if ( is_keyword( cur ) ) - { - // parses, token, if token identifies - // the container context (e.g. class/namespace) - // the corresponding context object is created - // and set as current context - - ParseKeyword( cur ); - continue; - } - - if ( *cur >= '0' && *cur <= '9' ) - { - skip_token( cur ); - continue; - } - - if ( *cur == '}' ) - { - if ( mCurCtxType != SP_CTX_CLASS ) - { - // FOR NOW:: disable the below assertion - - // DBG:: unexpected closing-bracket found - //ASSERT(0); - - skip_token( cur ); // just skip it - continue; - } - - if ( mpCurCtx->GetType() == SP_CTX_CLASS ) - { - int curOfs = ( (cur+1) - _gSrcStart ); - - mpCurCtx->mContextLength = ( curOfs - mpCurCtx->mSrcOffset ); - } - - --mNestingLevel; - - // terminate operation/class/namespace context - // TBD:: check if it's really this type of context - - wxASSERT( mpCurCtx ); - mpCurCtx = mpCurCtx->GetOutterContext(); - wxASSERT( mpCurCtx ); - - if ( mNestingLevel == 0 ) - { - - mCurCtxType = SP_CTX_FILE; - - // not-nested class delclaration finished, - // rest template flag in any case - mIsTemplate = 0; - } - - skip_token( cur ); - continue; - } - - bool isAMacro = 0; - - if ( is_function( cur, isAMacro ) ) - { - if ( isAMacro ) - { - skip_token( cur ); - continue; - } - - char* savedPos = cur; - - int tmpLnNo; - store_line_no( tmpLnNo ); - - isAMacro = FALSE; - - if ( !ParseNameAndRetVal( cur, isAMacro ) ) - { - if ( !isAMacro ) - { - cur = savedPos; - SkipFunction( cur ); - } - continue; - } - - if ( !ParseArguments( cur ) ) - { - // failure while parsing arguments, - // remove enclosing operation context + // set up state variables + mCurVis = SP_VIS_PRIVATE; + + spFile* pTopCtx = new spFile(); + mpCurCtx = pTopCtx; + + mIsVirtual = 0; + mIsTemplate = 0; + mNestingLevel = 0; + + cur = start; + + mpStart = start; + mpEnd = end; + + _gSrcEnd = mpEnd; // let all the C-functions "smell" the end of file + _gSrcStart = start; + + _gLineNo = 0; + + clear_commets_queue(); + + // main parsing loop + + do + { + if ( !get_next_token( cur ) ) + // end of source reached + return pTopCtx; + + if ( memcmp( cur, "ScriptSection( const string&", + strlen( "ScriptSection( const string&" ) + ) == 0 + ) + { + int o = 0; + ++o; + } + + switch (*cur) + { + case '#' : + { + AddMacroNode( cur ); + continue; + } + + case ':' : + { + skip_token( cur ); + continue; + } + + case ';' : + { + skip_token( cur ); + continue; + } + + case ')' : + { + skip_token( cur ); + continue; + } + + case '=' : + { + skip_token( cur ); + continue; + } + + default: break; + } + + // 'const' is a part of the return type, not a keyword here + if ( strncmp(cur, "const", 5) != 0 && is_keyword( cur ) ) + { + // parses, token, if token identifies + // the container context (e.g. class/namespace) + // the corresponding context object is created + // and set as current context + + ParseKeyword( cur ); + continue; + } + + if ( *cur >= '0' && *cur <= '9' ) + { + skip_token( cur ); + continue; + } + + if ( *cur == '}' ) + { + if ( mCurCtxType != SP_CTX_CLASS ) + { + // FOR NOW:: disable the below assertion + + // DBG:: unexpected closing-bracket found + //ASSERT(0); + + skip_token( cur ); // just skip it + continue; + } + + if ( mpCurCtx->GetType() == SP_CTX_CLASS ) + { + int curOfs = ( (cur+1) - _gSrcStart ); + + mpCurCtx->mContextLength = ( curOfs - mpCurCtx->mSrcOffset ); + } + + --mNestingLevel; + + // terminate operation/class/namespace context + // TBD:: check if it's really this type of context + + wxASSERT( mpCurCtx ); + mpCurCtx = mpCurCtx->GetOutterContext(); + wxASSERT( mpCurCtx ); + + if ( mNestingLevel == 0 ) + { + + mCurCtxType = SP_CTX_FILE; + + // not-nested class delclaration finished, + // rest template flag in any case + mIsTemplate = 0; + } + + skip_token( cur ); + continue; + } + + bool isAMacro = 0; + + if ( is_function( cur, isAMacro ) ) + { + if ( isAMacro ) + { + skip_token( cur ); + continue; + } + + char* savedPos = cur; + + int tmpLnNo; + store_line_no( tmpLnNo ); + + isAMacro = FALSE; + + if ( !ParseNameAndRetVal( cur, isAMacro ) ) + { + if ( !isAMacro ) + { + cur = savedPos; + SkipFunction( cur ); + } + continue; + } + + if ( !ParseArguments( cur ) ) + { + // failure while parsing arguments, + // remove enclosing operation context - spContext* pFailed = mpCurCtx; - mpCurCtx = mpCurCtx->GetOutterContext(); - mpCurCtx->RemoveChild( pFailed ); + spContext* pFailed = mpCurCtx; + mpCurCtx = mpCurCtx->GetOutterContext(); + mpCurCtx->RemoveChild( pFailed ); - skip_to_eol( cur ); - //cur = savedPos; - } - else - { - // otherwise, successfully close operation context: + skip_to_eol( cur ); + //cur = savedPos; + } + else + { + // otherwise, successfully close operation context: - clear_commets_queue(); + clear_commets_queue(); - SkipFunctionBody( cur ); + SkipFunctionBody( cur ); - mpCurCtx = mpCurCtx->GetOutterContext(); + mpCurCtx = mpCurCtx->GetOutterContext(); - // DBG:: - wxASSERT( mpCurCtx ); + // DBG:: + wxASSERT( mpCurCtx ); - } - } - else // otherwise it's declaration of a variable; - { - // now, the cursor point to the end of statement (';' token) + } + } + else // otherwise it's declaration of a variable; + { + // now, the cursor point to the end of statement (';' token) - if ( mCurCtxType != SP_CTX_CLASS ) - { - // non-class members are ignored + if ( mCurCtxType != SP_CTX_CLASS ) + { + // non-class members are ignored - skip_token( cur ); // skip the end of statement - continue; - } + skip_token( cur ); // skip the end of statement + continue; + } - ParseMemberVar( cur ); - } + ParseMemberVar( cur ); + } - } while( 1 ); + } while( 1 ); } void CJSourceParser::AttachComments( spContext& ctx, char* cur ) { - if ( !mCommentsOn ) return; + if ( !mCommentsOn ) return; + + MCommentListT& lst = ctx.GetCommentList(); - MCommentListT& lst = ctx.GetCommentList(); + char* prevComEnd = 0; - char* prevComEnd = 0; + int tmpLnNo; + store_line_no( tmpLnNo ); - int tmpLnNo; - store_line_no( tmpLnNo ); + // attach comments which were found before the given context - // attach comments which were found before the given context + for( int i = 0; i != _gCQSize; ++i ) + { + spComment* pComment = new spComment(); + lst.push_back( pComment ); - for( int i = 0; i != _gCQSize; ++i ) - { - spComment* pComment = new spComment(); - lst.push_back( pComment ); + // find the end of comment + char* start = _gCommentsQueue[i]; - // find the end of comment - char* start = _gCommentsQueue[i]; + pComment->mIsMultiline = ( *(start+1) == '*' ); - pComment->mIsMultiline = ( *(start+1) == '*' ); + // first comment in the queue and multiline + // comments are always treated as a begining + // of the new paragraph in the comment text - // first comment in the queue and multiline - // comments are always treated as a begining - // of the new paragraph in the comment text + if ( i == 0 ) - if ( i == 0 ) + pComment->mStartsPar = TRUE; + else + if ( pComment->mIsMultiline ) - pComment->mStartsPar = TRUE; - else - if ( pComment->mIsMultiline ) + pComment->mStartsPar = TRUE; + else + { + // find out wheather there is a new-line + // between to adjecent comments - pComment->mStartsPar = TRUE; - else - { - // find out wheather there is a new-line - // between to adjecent comments + char* prevLine = start; + skip_to_prev_line(prevLine); - char* prevLine = start; - skip_to_prev_line(prevLine); + if ( prevLine >= prevComEnd ) - if ( prevLine >= prevComEnd ) - - pComment->mStartsPar = TRUE; - else - pComment->mStartsPar = FALSE; - } + pComment->mStartsPar = TRUE; + else + pComment->mStartsPar = FALSE; + } - prevComEnd = set_comment_text( pComment->mText, start ); - } + prevComEnd = set_comment_text( pComment->mText, start ); + } - // attach comments which are at the end of the line - // of the given context (if any) + // attach comments which are at the end of the line + // of the given context (if any) - if ( skip_to_next_comment_in_the_line( cur ) ) - { - spComment* pComment = new spComment(); - lst.push_back( pComment ); - - set_comment_text( pComment->mText, cur ); + if ( skip_to_next_comment_in_the_line( cur ) ) + { + spComment* pComment = new spComment(); + lst.push_back( pComment ); - pComment->mStartsPar = 1; - pComment->mIsMultiline = ( *(cur+1) == '*' ); + set_comment_text( pComment->mText, cur ); - // mark this comment, so that it would not - // get in the comments list of the next context - _gLastSuppresedComment = cur; - } + pComment->mStartsPar = 1; + pComment->mIsMultiline = ( *(cur+1) == '*' ); - restore_line_no( tmpLnNo ); + // mark this comment, so that it would not + // get in the comments list of the next context + _gLastSuppresedComment = cur; + } - clear_commets_queue(); + restore_line_no( tmpLnNo ); + + clear_commets_queue(); } void CJSourceParser::AddMacroNode( char*& cur ) { - char* start = cur; + char* start = cur; + + int lineNo = get_line_no(); + + skip_preprocessor_dir( cur ); + + int tmpLnNo; + store_line_no( tmpLnNo ); + + if ( !mMacrosOn ) return; + + spPreprocessorLine* pPL = new spPreprocessorLine(); + pPL->mSrcLineNo = lineNo; - int lineNo = get_line_no(); + AttachComments( *pPL, cur ); - skip_preprocessor_dir( cur ); + get_string_between( start, cur, &pPL->mLine ); - int tmpLnNo; - store_line_no( tmpLnNo ); + ++start; // skip '#' + get_next_token( start ); - if ( !mMacrosOn ) return; + pPL->mDefType = SP_PREP_DEF_OTHER; - spPreprocessorLine* pPL = new spPreprocessorLine(); - pPL->mSrcLineNo = lineNo; + // if we found a definition or redefinition, + // determine the type exactly and assign + // a name to the context - AttachComments( *pPL, cur ); + if ( *start == 'd' ) + { + if ( cmp_tokens_fast( start, "define", 6 ) ) + { + char* tok = start+6; - get_string_between( start, cur, &pPL->mLine ); + get_next_token( tok ); - ++start; // skip '#' - get_next_token( start ); - - pPL->mDefType = SP_PREP_DEF_OTHER; + pPL->mName = get_token_str( tok ); - // if we found a definition or redefinition, - // determine the type exactly and assign - // a name to the context + skip_token( tok ); + get_next_token( tok); - if ( *start == 'd' ) - { - if ( cmp_tokens_fast( start, "define", 6 ) ) - { - char* tok = start+6; - get_next_token( tok ); + if ( tok > cur ) + pPL->mDefType = SP_PREP_DEF_DEFINE_SYMBOL; + else + pPL->mDefType = SP_PREP_DEF_REDEFINE_SYMBOL; + } + } + else if ( *start == 'i' ) + { + if ( cmp_tokens_fast( start, "include", 7 ) ) + { + pPL->mDefType = SP_PREP_DEF_INCLUDE_FILE; + } + else if ( *++start == 'f' ) + { + // either "#if" or "#ifdef" + cur = start; + skip_token( cur ); + get_next_token( cur ); - pPL->mName = get_token_str( tok ); + string condition = get_token_str( cur ); - skip_token( tok ); - get_next_token( tok); + // currently, everything except '0' is true + if ( condition == "0" ) { + // skip until the following else or enif + while ( cur < _gSrcEnd ) { + skip_to_eol( cur ); + skip_eol( cur ); + get_next_token( cur ); + if ( *cur++ == '#' && *cur == 'e' ) + break; + } + } - if ( tok > cur ) - pPL->mDefType = SP_PREP_DEF_DEFINE_SYMBOL; - else - pPL->mDefType = SP_PREP_DEF_REDEFINE_SYMBOL; - } - } - else - if ( *start == 'i' ) + // TODO parse the condition... + } + } + else if ( cmp_tokens_fast( start, "else", 4 ) ) + { + // skip until "#endif" + while ( cur < _gSrcEnd ) { + skip_to_eol( cur ); + skip_eol( cur ); - if ( cmp_tokens_fast( start, "include", 7 ) ) - { - pPL->mDefType = SP_PREP_DEF_INCLUDE_FILE; - } + get_next_token( cur ); + if ( *cur++ == '#' && cmp_tokens_fast( cur, "endif", 5 ) ) + break; + } + } - mpCurCtx->AddMember( pPL ); + mpCurCtx->AddMember( pPL ); - restore_line_no( tmpLnNo ); + skip_to_eol( cur ); + skip_eol( cur ); - clear_commets_queue(); + restore_line_no( tmpLnNo ); + + clear_commets_queue(); } void CJSourceParser::ParseKeyword( char*& cur ) { - // analyze token, which identifies the begining of a new context - - if ( CheckVisibilty( cur ) ) - { - skip_token( cur ); - return; - } - - if ( is_class_token( cur ) ) - { - if ( is_forward_decl( cur ) ) - { - // forward declarations are ignored; - skip_token( cur ); - return; - } - - if ( mNestingLevel == 0 ) - { - // change context form global class context - mCurCtxType = SP_CTX_CLASS; - } - - ++mNestingLevel; - - // add information about new class (name, inheritance, etc) - AddClassNode( cur ); - - // the default visiblity for class members is 'private' - mCurVis = SP_VIS_PRIVATE; - - return; - } - - size_t len = get_token_len( cur ); - - if ( cmp_tokens_fast( cur, "typedef", len ) ) - { - skip_token(cur); - get_next_token(cur); - - if ( cmp_tokens_fast( cur, "struct", len ) || - cmp_tokens_fast( cur, "union", len ) || - cmp_tokens_fast( cur, "class", len ) - ) - { - if ( mNestingLevel == 0 ) - { - // change context form global class context - mCurCtxType = SP_CTX_CLASS; - } - - ++mNestingLevel; - - // add information about new class (name, inheritance, etc) - AddClassNode( cur ); - - // the default visiblity for class members is 'private' - mCurVis = SP_VIS_PRIVATE; - - return; - - // FOR NOW:: typedef struct, etc are also ignored - //skip_scope_block( cur ); - } - - if ( cmp_tokens_fast( cur, "enum", len ) ) - { - AddEnumNode( cur ); - return; - } - - AddTypeDefNode( cur ); - - return; - } - - if ( cmp_tokens_fast( cur, "enum", len ) ) - { - AddEnumNode( cur ); - return; - } - - if ( cmp_tokens_fast( cur, "extern", len ) ) - { - // extern's are ignored (both extern "C" and extern vars) - while ( *cur != '{' && - *cur != ';' ) - { - skip_token( cur ); - get_next_token( cur ); - } - return; - - } - if ( cmp_tokens_fast( cur, "enum", len ) ) - { - // enumeration blocks are ignored - - skip_scope_block( cur ); - - get_next_token( cur ); - skip_token( cur ); // skip ';' token; - return; - } - - if ( cmp_tokens_fast( cur, "package", len ) ) - { - // packages are ignored - skip_statement( cur ); - return; - }; - - if ( cmp_tokens_fast( cur, "import", len ) ) - { - // import statements are ignored - skip_statement( cur ); - return; - } - - if ( cmp_tokens_fast( cur, "virtual", len ) ) - { - // probably the virtual method is in front of us; - mIsVirtaul = 1; - skip_token( cur ); - return; - } - - if ( cmp_tokens_fast( cur, "template", len ) ) - { - mIsTemplate = 1; - skip_tempalate_statement( cur ); - return; - } - - if ( cmp_tokens_fast( cur, "friend", len ) ) - { - skip_statement( cur ); - return; - } - - // ingnore "unsigificant" tokens (i.e. which do not - // affect the current parsing context) - - skip_token( cur ); + // analyze token, which identifies the begining of a new context + + if ( CheckVisibilty( cur ) ) + { + skip_token( cur ); + return; + } + + if ( is_class_token( cur ) ) + { + if ( is_forward_decl( cur ) ) + { + // forward declarations are ignored; + skip_token( cur ); + return; + } + + if ( mNestingLevel == 0 ) + { + // change context form global class context + mCurCtxType = SP_CTX_CLASS; + } + + ++mNestingLevel; + + // add information about new class (name, inheritance, etc) + AddClassNode( cur ); + + // the default visiblity for class members is 'private' + mCurVis = SP_VIS_PRIVATE; + + return; + } + + size_t len = get_token_len( cur ); + + if ( cmp_tokens_fast( cur, "typedef", len ) ) + { + skip_token(cur); + get_next_token(cur); + + if ( cmp_tokens_fast( cur, "struct", len ) || + cmp_tokens_fast( cur, "union", len ) || + cmp_tokens_fast( cur, "class", len ) + ) + { + if ( mNestingLevel == 0 ) + { + // change context form global class context + mCurCtxType = SP_CTX_CLASS; + } + + ++mNestingLevel; + + // add information about new class (name, inheritance, etc) + AddClassNode( cur ); + + // the default visiblity for class members is 'private' + mCurVis = SP_VIS_PRIVATE; + + return; + + // FOR NOW:: typedef struct, etc are also ignored + //skip_scope_block( cur ); + } + + if ( cmp_tokens_fast( cur, "enum", len ) ) + { + AddEnumNode( cur ); + return; + } + + AddTypeDefNode( cur ); + + return; + } + + if ( cmp_tokens_fast( cur, "enum", len ) ) + { + AddEnumNode( cur ); + return; + } + + if ( cmp_tokens_fast( cur, "extern", len ) ) + { + // extern's are ignored (both extern "C" and extern vars) + while ( *cur != '{' && + *cur != ';' ) + { + skip_token( cur ); + get_next_token( cur ); + } + return; + + } + if ( cmp_tokens_fast( cur, "enum", len ) ) + { + // enumeration blocks are ignored + + skip_scope_block( cur ); + + get_next_token( cur ); + skip_token( cur ); // skip ';' token; + return; + } + + if ( cmp_tokens_fast( cur, "package", len ) ) + { + // packages are ignored + skip_statement( cur ); + return; + }; + + if ( cmp_tokens_fast( cur, "import", len ) ) + { + // import statements are ignored + skip_statement( cur ); + return; + } + + if ( cmp_tokens_fast( cur, "virtual", len ) ) + { + // probably the virtual method is in front of us; + mIsVirtual = 1; + skip_token( cur ); + return; + } + + if ( cmp_tokens_fast( cur, "template", len ) ) + { + mIsTemplate = 1; + skip_tempalate_statement( cur ); + return; + } + + if ( cmp_tokens_fast( cur, "friend", len ) ) + { + skip_statement( cur ); + return; + } + + // ingnore "unsigificant" tokens (i.e. which do not + // affect the current parsing context) + + skip_token( cur ); } bool CJSourceParser::ParseNameAndRetVal( char*& cur, bool& isAMacro ) { - isAMacro = FALSE; + isAMacro = FALSE; + + // FOR NOW:: all functions in the global + // scope are ignored + + int lineNo = get_line_no(); + + char* start = cur; - // FOR NOW:: all functions in the global - // scope are ignored + bool isVirtual = false; + while( *cur != '(' ) + { + if ( get_token_str( cur ) == "virtual" ) + isVirtual = true; - int lineNo = get_line_no(); + skip_token( cur ); + if ( !get_next_token( cur ) ) return FALSE; + } - char* start = cur; + char* bracketPos = cur; + char* savedPos = cur + 1; - while( *cur != '(' ) - { - skip_token( cur ); - if ( !get_next_token( cur ) ) return FALSE; - } + int tmpLnNo; + store_line_no( tmpLnNo ); - char* bracketPos = cur; - char* savedPos = cur + 1; + // skip gap between function name and start of paramters list + while ( *(cur-1) == ' ' ) + --cur; - int tmpLnNo; - store_line_no( tmpLnNo ); + // check if it's not a macro, and let plugin handle it, if so - // skip gap between function name and start of paramters list - while ( *(cur-1) == ' ' ) - --cur; + if ( mpPlugin ) + { + skip_token_back( cur ); - // check if it's not a macro, and let plugin handle it, if so + char* tmp = cur; - if ( mpPlugin ) - { - skip_token_back( cur ); + if ( mpPlugin->CanUnderstandContext( tmp, _gSrcEnd, mpCurCtx ) ) + { + cur = tmp; - char* tmp = cur; + mpPlugin->ParseContext( _gSrcStart, cur, _gSrcEnd, mpCurCtx ); - if ( mpPlugin->CanUnderstandContext( tmp, _gSrcEnd, mpCurCtx ) ) - { - cur = tmp; + isAMacro = TRUE; - mpPlugin->ParseContext( _gSrcStart, cur, _gSrcEnd, mpCurCtx ); + return FALSE; + } + } - isAMacro = TRUE; + spOperation* pOp = new spOperation(); - return FALSE; - } - } + pOp->mSrcLineNo = lineNo; + pOp->mSrcOffset = int( start - _gSrcStart ); + pOp->mHeaderLength = int( bracketPos - start ); + if ( mpCurCtx->GetContextType() == SP_CTX_CLASS ) + pOp->mScope = mpCurCtx->mName; - spOperation* pOp = new spOperation(); + mpCurCtx->AddMember( pOp ); + pOp->mVisibility = mCurVis; + pOp->mIsVirtual = isVirtual; - pOp->mSrcLineNo = lineNo; - pOp->mSrcOffset = int( start - _gSrcStart ); - pOp->mHeaderLength = int( bracketPos - start ); + // add comments about operation + AttachComments( *pOp, cur ); - mpCurCtx->AddMember( pOp ); - pOp->mVisibility = mCurVis; + // go backwards to method name + skip_token_back( cur ); - // add comments about operation - AttachComments( *pOp, cur ); + pOp->mName = get_token_str( cur ); - // go backwards to method name - skip_token_back( cur ); + // checker whether it's not an operator + char chFirst = *pOp->mName.c_str(); + if ( !isalpha(chFirst) && chFirst != '_' && chFirst != '~' ) { + // skip 'operator' + skip_next_token_back( cur ); + skip_token_back( cur ); - pOp->mName = get_token_str( cur ); + string lastToken = get_token_str( cur ); + if ( lastToken == "operator" ) { + lastToken += pOp->mName; + pOp->mName = lastToken; + } + else { + // ok, it wasn't an operator after all + skip_token( cur ); + } + } + else if ( pOp->mName == "operator" ) { + skip_token( cur ); + get_next_token( cur ); + string oper = get_token_str( cur ); - // go backwards to method return type - skip_next_token_back( cur ); + pOp->mName += oper; + } - if ( cur >= start ) + // go backwards to method return type + skip_next_token_back( cur ); - pOp->mRetType = string( start, size_t( cur-start ) ); + if ( cur >= start ) + { + string rettype = string( start, size_t( cur-start ) ); + rettype.Replace("WXDLLEXPORT ", ""); // FIXME just for now... + pOp->mRetType = rettype; + } - arrange_indirection_tokens_between( pOp->mRetType, pOp->mName ); + arrange_indirection_tokens_between( pOp->mRetType, pOp->mName ); - cur = savedPos; - restore_line_no( tmpLnNo ); + cur = savedPos; + restore_line_no( tmpLnNo ); - // now, enter operation context - mpCurCtx = pOp; + // now, enter operation context + mpCurCtx = pOp; - return TRUE; + return TRUE; } bool CJSourceParser::ParseArguments( char*& cur ) { - // DANGER-MACROS:: + // DANGER-MACROS:: + + // now cursor position is right after the first opening bracket + // of the function declaration + + char* blocks [16]; // used exclusivelly for iterative "lean out" + // of macros and misc. not-obviouse grammar + // (dirty,, but we cannot do it very nice, + // we're not preprocessor-free C/C++ code) + int blockSizes[16]; + + do + { + size_t blocksSkipped = 0; + + get_next_token( cur ); + + bool first_blk = 1; + + while( *cur != ')' && *cur != ',' ) + { + blocks[blocksSkipped] = cur; + + if ( first_blk ) + { + char* prev = cur; + skip_token( cur ); + + blockSizes[blocksSkipped] = size_t(cur-prev); + + first_blk = 0; + } + else + blockSizes[blocksSkipped] = skip_block( cur ); + + get_next_token( cur ); + ++blocksSkipped; + } + - // now cursor position is right after the first opening bracket - // of the function declaration + if ( blocksSkipped == 1 ) + { + // check if the empty arg. list stressed with "void" inside + if ( cmp_tokens_fast( blocks[0] , "void", 4 ) ) + { + cur++; // skip ')' - char* blocks [16]; // used exclusivelly for iterative "lean out" - // of macros and misc. not-obviouse grammar - // (dirty,, but we cannot do it very nice, - // we're not preprocessor-free C/C++ code) - int blockSizes[16]; + break; + } - do - { - size_t blocksSkipped = 0; + // FIXME:: TBD:: K&R-style function declarations! - get_next_token( cur ); + // if only one block enclosed, than it's probably + // some macro, there should be at least two blocks, + // one for argument type and another for it's identifier + return FALSE; + } - bool first_blk = 1; + if ( blocksSkipped == 0 ) + { + if ( *cur == 10 ) ++_gLineNo; + ++cur; // skip ')' - while( *cur != ')' && *cur != ',' ) - { - blocks[blocksSkipped] = cur; + break; // function without paramters + } - if ( first_blk ) - { - char* prev = cur; - skip_token( cur ); + // we should be in the operation context now + spOperation* pOp = (spOperation*)mpCurCtx; - blockSizes[blocksSkipped] = size_t(cur-prev); + spParameter* pPar = new spParameter(); - first_blk = 0; - } - else - blockSizes[blocksSkipped] = skip_block( cur ); + pOp->AddMember( pPar ); + // FOR NOW:: line number is not exact if argument list is mutiline + pPar->mSrcLineNo = get_line_no(); - get_next_token( cur ); - ++blocksSkipped; - } + size_t nameBlock = blocksSkipped - 1; + size_t typeBlock = nameBlock - 1; + // check if default values present + if ( *blocks[typeBlock] == '=' ) + { + // expressions like "int = 5" are ignored, + // since name for paramters is required + if ( blocksSkipped == 3 ) + { + if ( *cur == ')' ) + { + ++cur; + break; + } + else + continue; + } - if ( blocksSkipped == 1 ) - { - // check if the empty arg. list stressed with "void" inside - if ( cmp_tokens_fast( blocks[0] , "void", 4 ) ) - return TRUE; + pPar->mInitVal = string( blocks[nameBlock], blockSizes[nameBlock] ); - // FIXME:: TBD:: K&R-style function declarations! + nameBlock = nameBlock - 2; // skip '=' token and default value block + typeBlock = nameBlock - 1; + } - // if only one block enclosed, than it's probably - // some macro, there should be at least two blocks, - // one for argument type and another for it's identifier - return FALSE; - } - - if ( blocksSkipped == 0 ) - { - if ( *cur == 10 ) ++_gLineNo; - ++cur; - break; // function without paramters - } - - // we should be in the operation context now - spOperation* pOp = (spOperation*)mpCurCtx; - - spParameter* pPar = new spParameter(); - - pOp->AddMember( pPar ); - // FOR NOW:: line number is not exact if argument list is mutiline - pPar->mSrcLineNo = get_line_no(); + // attach comments about the parameter + AttachComments( *pPar, blocks[nameBlock] ); - size_t nameBlock = blocksSkipped - 1; - size_t typeBlock = nameBlock - 1; - - // check if default values present - if ( *blocks[typeBlock] == '=' ) - { - // expressions like "int = 5" are ignored, - // since name for paramters is required - if ( blocksSkipped == 3 ) - { - if ( *cur == ')' ) - { - ++cur; - break; - } - else - continue; - } - - pPar->mInitVal = string( blocks[nameBlock], blockSizes[nameBlock] ); - - nameBlock = nameBlock - 2; // skip '=' token and default value block - typeBlock = nameBlock - 1; - } - - // attach comments about the parameter - AttachComments( *pPar, blocks[nameBlock] ); - - // retrieve argument name - pPar->mName = string( blocks[nameBlock], blockSizes[nameBlock] ); - - // retreive argument type - - size_t len = blockSizes[ typeBlock ]; - len = size_t ( (blocks[ typeBlock ] + len) - blocks[ 0 ] ); - - pPar->mType = string( blocks[0], len ); - - arrange_indirection_tokens_between( pPar->mType, pOp->mName ); - - if ( *cur == ')' ) - { - ++cur; - break; - } - - ++cur; // skip comma - get_next_token(cur); - - } while(1); - - // check if it was really a function not a macro, - // if so, than it should be terminated with semicolon ';' - // or opening implemenetaton bracket '{' - - char* tok = cur; - - int tmpLnNo; - store_line_no( tmpLnNo ); - - do - { - if ( *tok == '{' || *tok == ';' ) - { - restore_line_no(tmpLnNo); - return TRUE; - } - - // check for unexpected tokens - if ( *tok == '=' || *tok == '0' ) - { - skip_token(tok); - if ( !get_next_token(tok) ) return FALSE; - continue; - } - - if ( *tok == '}' ) return FALSE; - - // if initialization list found - if ( *tok == ':' ) - { - restore_line_no(tmpLnNo); - return TRUE; - } - - if ( cmp_tokens_fast( tok, "const", 5 ) ) - { - skip_token(tok); - if ( !get_next_token(tok) ) return FALSE; - continue; - } - - if ( CheckVisibilty( tok ) ) return FALSE; - - // if next context found - if ( is_keyword( tok ) ) return FALSE; - - skip_token(tok); - if ( !get_next_token(tok) ) return FALSE; - - } while(1); - - return TRUE; + // retrieve argument name + pPar->mName = string( blocks[nameBlock], blockSizes[nameBlock] ); + + // retreive argument type + + size_t len = blockSizes[ typeBlock ]; + len = size_t ( (blocks[ typeBlock ] + len) - blocks[ 0 ] ); + + pPar->mType = string( blocks[0], len ); + + arrange_indirection_tokens_between( pPar->mType, pPar->mName ); + + if ( *cur == ')' ) + { + ++cur; + break; + } + + ++cur; // skip comma + get_next_token(cur); + + } while(1); + + // skip possible whitespace between ')' and following "const" + while ( isspace(*cur) ) + cur++; + + // check if it was really a function not a macro, + // if so, than it should be terminated with semicolon ';' + // or opening implemenetaton bracket '{' + + char* tok = cur; + + int tmpLnNo; + store_line_no( tmpLnNo ); + + do + { + if ( *tok == '{' || *tok == ';' ) + { + restore_line_no(tmpLnNo); + return TRUE; + } + + // check for unexpected tokens + if ( *tok == '=' || *tok == '0' ) + { + skip_token(tok); + if ( !get_next_token(tok) ) return FALSE; + continue; + } + + if ( *tok == '}' ) return FALSE; + + // if initialization list found + if ( *tok == ':' ) + { + restore_line_no(tmpLnNo); + return TRUE; + } + + if ( cmp_tokens_fast( tok, "const", 5 ) ) + { + ((spOperation*)mpCurCtx)->mIsConstant = true; + + skip_token(tok); + if ( !get_next_token(tok) ) return FALSE; + continue; + } + + if ( CheckVisibilty( tok ) ) return FALSE; + + // if next context found + if ( is_keyword( tok ) ) return FALSE; + + skip_token(tok); + if ( !get_next_token(tok) ) return FALSE; + + } while(1); + + return TRUE; } void CJSourceParser::ParseMemberVar( char*& cur ) { - MMemberListT& members = mpCurCtx->GetMembers(); + MMemberListT& members = mpCurCtx->GetMembers(); - bool firstMember = 1; + bool firstMember = 1; - size_t first = 0; + size_t first = 0; - string type; + string type; - // jump to the end of statement - // and start collecting same-type varibles - // back-to-front towards the type identifier + // jump to the end of statement + // and start collecting same-type varibles + // back-to-front towards the type identifier - skip_statement( cur ); - char* savedPos = cur; + skip_statement( cur ); + char* savedPos = cur; - int tmpLnNo; - store_line_no( tmpLnNo ); + int tmpLnNo; + store_line_no( tmpLnNo ); --cur; // rewind back to ';' - do - { - spAttribute* pAttr = new spAttribute(); - // FOR NOW:: line not is not exact, if member declaration is multiline - pAttr->mSrcLineNo = get_line_no(); + do + { + spAttribute* pAttr = new spAttribute(); + // FOR NOW:: line not is not exact, if member declaration is multiline + pAttr->mSrcLineNo = get_line_no(); + + mpCurCtx->AddMember( pAttr ); + pAttr->mVisibility = mCurVis; - mpCurCtx->AddMember( pAttr ); - pAttr->mVisibility = mCurVis; + pAttr->mIsConstant = 0; - pAttr->mIsConstant = 0; + if ( firstMember ) + { + firstMember = 0; + first = members.size() - 1;; + } - if ( firstMember ) - { - firstMember = 0; - first = members.size() - 1;; - } + skip_token_back( cur ); - skip_token_back( cur ); + // attach comments about the attribute + AttachComments( *pAttr, cur ); - // attach comments about the attribute - AttachComments( *pAttr, cur ); + pAttr->mName = get_token_str( cur ); - pAttr->mName = get_token_str( cur ); + // guessing that this going to be variable type + skip_next_token_back( cur ); + skip_token_back( cur ); - // guessing that this going to be variable type - skip_next_token_back( cur ); - skip_token_back( cur ); + pAttr->mType = get_token_str( cur ); - pAttr->mType = get_token_str( cur ); + // if comma, than variable list continues + // otherwise the variable type reached - stop - // if comma, than variable list continues - // otherwise the variable type reached - stop + if ( *cur == '=' ) + { + // yes, we've mistaken, it was not a identifier, + // but it's default value + pAttr->mInitVal = + pAttr->mName; - if ( *cur == '=' ) - { - // yes, we've mistaken, it was not a identifier, - // but it's default value - pAttr->mInitVal = - pAttr->mName; - - // skip default value and '=' symbol - skip_next_token_back( cur ); - skip_token_back( cur ); + // skip default value and '=' symbol + skip_next_token_back( cur ); + skip_token_back( cur ); - pAttr->mName = get_token_str( cur ); + pAttr->mName = get_token_str( cur ); - skip_next_token_back( cur ); - skip_token_back( cur ); - } + skip_next_token_back( cur ); + skip_token_back( cur ); + } - if ( *cur != ',' ) - { - type = get_token_str( cur ); - break; - } + if ( *cur != ',' ) + { + type = get_token_str( cur ); + break; + } - } while(1); + } while(1); - // set up types for all collected (same-type) attributes; - while ( first != members.size() - 1 ) - { - spAttribute* pAttr = (spAttribute*)members[first]; + first = 0; - pAttr->mType = type; - pAttr->mVisibility = mCurVis; + // set up types for all collected (same-type) attributes; + while ( first != members.size() - 1 ) + { + spAttribute* pAttr = members[first++]->CastToAttribute(); + if ( !pAttr ) + continue; - arrange_indirection_tokens_between( pAttr->mType, pAttr->mName ); + if ( !pAttr->mType ) + pAttr->mType = type; + pAttr->mVisibility = mCurVis; - ++first; - } + if ( !!pAttr->mName ) + arrange_indirection_tokens_between( pAttr->mType, pAttr->mName ); + } - cur = savedPos; - restore_line_no( tmpLnNo ); + cur = savedPos; + restore_line_no( tmpLnNo ); - clear_commets_queue(); + clear_commets_queue(); } void CJSourceParser::SkipFunction( char*& cur ) { - while ( *cur != '(' && cur < _gSrcEnd ) - { - if (*cur == 10 ) ++_gLineNo; - ++cur; - } + while ( *cur != '(' && cur < _gSrcEnd ) + { + if (*cur == 10 ) ++_gLineNo; + ++cur; + } - skip_next_token_back( cur ); // go back and skip function identifier - skip_token_back( cur ); // go back and skip return type + skip_next_token_back( cur ); // go back and skip function identifier + skip_token_back( cur ); // go back and skip return type - skip_block( cur ); // now, go ahead and skip whole declaration + skip_block( cur ); // now, go ahead and skip whole declaration - SkipFunctionBody( cur ); + SkipFunctionBody( cur ); } void CJSourceParser::SkipFunctionBody( char*& cur ) { - // FIXME:: check for comments and quoted stirngs here + // FIXME:: check for comments and quoted stirngs here - bool hasDefinition = FALSE; + bool hasDefinition = FALSE; - while( *cur != '{' && *cur != ';' ) - { - if (*cur == 10 ) ++_gLineNo; - ++cur; - } + while( *cur != '{' && *cur != ';' ) + { + if (*cur == 10 ) ++_gLineNo; + ++cur; + } - if ( *cur == ';' ) - { - ++cur; - } - else - { - hasDefinition = TRUE; + if ( *cur == ';' ) + { + ++cur; + } + else + { + hasDefinition = TRUE; - skip_scope_block( cur ); // skip the whole imp. - } + skip_scope_block( cur ); // skip the whole imp. + } - if ( mpCurCtx->GetType() == SP_CTX_OPERATION ) - { - spOperation& op = *((spOperation*)mpCurCtx); + if ( mpCurCtx->GetType() == SP_CTX_OPERATION ) + { + spOperation& op = *((spOperation*)mpCurCtx); - int curOfs = int ( cur - _gSrcStart ); + int curOfs = int ( cur - _gSrcStart ); - op.mContextLength = curOfs - mpCurCtx->mSrcOffset; + op.mContextLength = curOfs - mpCurCtx->mSrcOffset; - op.mHasDefinition = hasDefinition; + op.mHasDefinition = hasDefinition; - // separate scope resolution token from the name of operation + // separate scope resolution token from the name of operation - for( size_t i = 0; i != op.mName.length(); ++i ) - { - if ( op.mName[i] == ':' && op.mName[i+1] == ':' ) - { - string unscoped( op.mName, i+2, op.mName.length() - ( i + 2 ) ); + for( size_t i = 0; i != op.mName.length(); ++i ) + { + if ( op.mName[i] == ':' && op.mName[i+1] == ':' ) + { + string unscoped( op.mName, i+2, op.mName.length() - ( i + 2 ) ); - op.mScope = string( op.mName, 0, i ); + op.mScope = string( op.mName, 0, i ); - op.mName = unscoped; + op.mName = unscoped; - break; - } - } - } + break; + } + } + } } bool CJSourceParser::CheckVisibilty( char*& cur ) { - size_t len = get_token_len( cur ); - - if ( cmp_tokens_fast( cur, "public:", len ) ) - { - mCurVis = SP_VIS_PUBLIC; - return TRUE; - } - - if ( cmp_tokens_fast( cur, "protected:", len ) ) - { - mCurVis = SP_VIS_PROTECTED; - return TRUE; - } - - if ( cmp_tokens_fast( cur, "private:", len ) ) - { - mCurVis = SP_VIS_PRIVATE; - return TRUE; - } - - return FALSE; + size_t len = get_token_len( cur ); + + if ( cmp_tokens_fast( cur, "public:", len ) ) + { + mCurVis = SP_VIS_PUBLIC; + return TRUE; + } + + if ( cmp_tokens_fast( cur, "protected:", len ) ) + { + mCurVis = SP_VIS_PROTECTED; + return TRUE; + } + + if ( cmp_tokens_fast( cur, "private:", len ) ) + { + mCurVis = SP_VIS_PRIVATE; + return TRUE; + } + + return FALSE; } void CJSourceParser::AddClassNode( char*& cur ) { - char* ctxStart = cur; + char* ctxStart = cur; - skip_token( cur ); // skip 'class' keyword - if ( !get_next_token( cur ) ) return; + string classkeyword = get_token_str( cur ); - // in C++ - if ( *cur == ':' ) - { - skip_token( cur ); - get_next_token( cur ); - } + skip_token( cur ); // skip 'class' keyword + if ( !get_next_token( cur ) ) return; - spClass* pClass = new spClass(); + // in C++ + if ( *cur == ':' ) + { + skip_token( cur ); + get_next_token( cur ); + } + // by default all class members are private + mCurVis = SP_VIS_PRIVATE; - mpCurCtx->AddMember( pClass ); + spClass* pClass = new spClass(); + if ( classkeyword == "class" ) + pClass->mClassSubType = SP_CLTYPE_CLASS; + else if ( classkeyword == "struct" ) { + pClass->mClassSubType = SP_CLTYPE_STRUCTURE; - // by default all class members are private - mCurVis = SP_VIS_PRIVATE; + mCurVis = SP_VIS_PUBLIC; + } + else if ( classkeyword == "union" ) { + pClass->mClassSubType = SP_CLTYPE_UNION; - // attach comments about the class - AttachComments( *pClass, cur ); + mCurVis = SP_VIS_PUBLIC; + } + else if ( classkeyword == "interface" ) + pClass->mClassSubType = SP_CLTYPE_INTERFACE; + else { + pClass->mClassSubType = SP_CLTYPE_INVALID; - pClass->mSrcLineNo = get_line_no(); + wxFAIL_MSG("unknown class keyword"); + } - pClass->mSrcOffset = int( ctxStart - _gSrcStart ); + mpCurCtx->AddMember( pClass ); - char* nameTok = cur; - pClass->mName = get_token_str( cur ); + // attach comments about the class + AttachComments( *pClass, cur ); - bool isDerived = 0; + pClass->mSrcLineNo = get_line_no(); - // DANGER-MACROS:: + pClass->mSrcOffset = int( ctxStart - _gSrcStart ); - do - { - skip_token( cur ); - if ( !get_next_token( cur ) ) return; + char* nameTok = cur; + pClass->mName = get_token_str( cur ); - if ( *cur == ':' ) - { - isDerived = 1; + bool isDerived = 0; - char* tok = cur; + // DANGER-MACROS:: - int tmpLn; - store_line_no( tmpLn ); + do + { + skip_token( cur ); + if ( !get_next_token( cur ) ) return; - skip_next_token_back( tok ); - skip_token_back( tok ); + if ( *cur == ':' ) + { + isDerived = 1; - restore_line_no( tmpLn ); + char* tok = cur; - // class name should precend ':' colon, thus - // the one which was captured before was - // proablty something else (like __dllexport MyClass : ... ) + int tmpLn; + store_line_no( tmpLn ); - if ( nameTok != tok ) - { - pClass->mName = get_token_str( tok ); - } + skip_next_token_back( tok ); + skip_token_back( tok ); - } + restore_line_no( tmpLn ); - if ( *cur == '{' ) - break; + // class name should precend ':' colon, thus + // the one which was captured before was + // proablty something else (like __dllexport MyClass : ... ) - if ( *cur == ',' ) - continue; + if ( nameTok != tok ) + { + pClass->mName = get_token_str( tok ); + } - size_t len = get_token_len( cur ); + } - // skip neglectable C++ modifieres - if ( cmp_tokens_fast( cur, "public", len ) ) - continue; + if ( *cur == '{' ) + break; - if ( cmp_tokens_fast( cur, "protected", len ) ) - continue; + if ( *cur == ',' ) + continue; - if ( cmp_tokens_fast( cur, "private", len ) ) - continue; + size_t len = get_token_len( cur ); - if ( cmp_tokens_fast( cur, "virtual", len ) ) - continue; + // skip neglectable C++ modifieres + if ( cmp_tokens_fast( cur, "public", len ) ) + continue; - // skip neglectable JAVA modifieres + if ( cmp_tokens_fast( cur, "protected", len ) ) + continue; - if ( cmp_tokens_fast( cur, "extends", len ) ) - { - isDerived = 1; - continue; - } + if ( cmp_tokens_fast( cur, "private", len ) ) + continue; - if ( cmp_tokens_fast( cur, "implements", len ) ) - { - isDerived = 1; - continue; - } + if ( cmp_tokens_fast( cur, "virtual", len ) ) + continue; - // all we need to know is superclass or interface + // skip neglectable JAVA modifieres - char* tok = cur; - int tmpLn; - store_line_no( tmpLn ); + if ( cmp_tokens_fast( cur, "extends", len ) ) + { + isDerived = 1; + continue; + } - skip_token(tok); - get_next_token(tok); + if ( cmp_tokens_fast( cur, "implements", len ) ) + { + isDerived = 1; + continue; + } - restore_line_no( tmpLn ); - - if ( *tok != ':' && *cur != ':' ) - - pClass->mSuperClassNames.push_back( string( cur, len ) ); + // all we need to know is superclass or interface - } while(1); + char* tok = cur; + int tmpLn; + store_line_no( tmpLn ); - if ( !isDerived ) - { - int tmpLn; - store_line_no( tmpLn ); + skip_token(tok); + get_next_token(tok); - while ( pClass->mSuperClassNames.size() ) + restore_line_no( tmpLn ); - pClass->mSuperClassNames.erase( &pClass->mSuperClassNames[0] ); + if ( *tok != ':' && *cur != ':' ) - char* tok = cur; + pClass->mSuperClassNames.push_back( string( cur, len ) ); - // some non-obviouse token was following "class" keyword - - // we've confused it with class name - thus now we're reverting this mistake + } while(1); - skip_next_token_back( tok ); - skip_token_back( tok ); + if ( !isDerived ) + { + int tmpLn; + store_line_no( tmpLn ); - pClass->mName = get_token_str( tok ); + while ( pClass->mSuperClassNames.size() ) - restore_line_no( tmpLn ); - } + pClass->mSuperClassNames.erase( &pClass->mSuperClassNames[0] ); + char* tok = cur; - ++cur; // skip opening curly brace + // some non-obviouse token was following "class" keyword - + // we've confused it with class name - thus now we're reverting this mistake - pClass->mHeaderLength = ( cur - ctxStart ); + skip_next_token_back( tok ); + skip_token_back( tok ); - // now, enter the class context - mpCurCtx = pClass; + pClass->mName = get_token_str( tok ); - clear_commets_queue(); + restore_line_no( tmpLn ); + } + + + ++cur; // skip opening curly brace + + pClass->mHeaderLength = ( cur - ctxStart ); + + // now, enter the class context + mpCurCtx = pClass; + + clear_commets_queue(); } void CJSourceParser::AddEnumNode( char*& cur ) { - // now the cursor is at "enum" keyword - char* start = cur; + // now the cursor is at "enum" keyword + char* start = cur; + + spEnumeration* pEnum = new spEnumeration(); + mpCurCtx->AddMember( pEnum ); - spEnumeration* pEnum = new spEnumeration(); - mpCurCtx->AddMember( pEnum ); + pEnum->mSrcLineNo = get_line_no(); - pEnum->mSrcLineNo = get_line_no(); + AttachComments( *pEnum, cur ); - AttachComments( *pEnum, cur ); + skip_token( cur ); + if ( !get_next_token( cur ) ) return; - skip_token( cur ); - if ( !get_next_token( cur ) ) return; + // check if enumeration has got it's identifier + if ( *cur != '{' ) + { + pEnum->mName = get_token_str( cur ); + } - // check if enumeration has got it's identifier - if ( *cur != '{' ) - { - pEnum->mName = get_token_str( cur ); - } + if ( !skip_imp_block( cur ) ) return; - if ( !skip_imp_block( cur ) ) return; + get_string_between( start, cur, &pEnum->mEnumContent ); - get_string_between( start, cur, &pEnum->mEnumContent ); + if ( get_next_token(cur) ) + { + // check if the identifier if after the {...} block + if ( *cur != ';' ) - if ( get_next_token(cur) ) - { - // check if the identifier if after the {...} block - if ( *cur != ';' ) - - pEnum->mName = get_token_str( cur ); - } + pEnum->mName = get_token_str( cur ); + } - clear_commets_queue(); + clear_commets_queue(); } void CJSourceParser::AddTypeDefNode( char*& cur ) { - // now the cursor at the token next to "typedef" keyword + // now the cursor at the token next to "typedef" keyword + + if ( !get_next_token(cur) ) return; - if ( !get_next_token(cur) ) return; + char* start = cur; - char* start = cur; + spTypeDef* pTDef = new spTypeDef(); + mpCurCtx->AddMember( pTDef ); - spTypeDef* pTDef = new spTypeDef(); - mpCurCtx->AddMember( pTDef ); + pTDef->mSrcLineNo = get_line_no(); - pTDef->mSrcLineNo = get_line_no(); + AttachComments( *pTDef, cur ); - AttachComments( *pTDef, cur ); + skip_statement( cur ); - skip_statement( cur ); + int tmpLnNo; + store_line_no( tmpLnNo ); - int tmpLnNo; - store_line_no( tmpLnNo ); + char* tok = cur-1; + skip_next_token_back( tok ); - char* tok = cur-1; - skip_next_token_back( tok ); + char* nameEnd = tok; - char* nameEnd = tok; + skip_token_back( tok ); - skip_token_back( tok ); + char* nameStart = tok; - char* nameStart = tok; + skip_next_token_back( tok ); - skip_next_token_back( tok ); + char* typeEnd = tok; - char* typeEnd = tok; + // check if it's function prototype + if ( *nameStart == ')' ) + { + typeEnd = nameStart+1; - // check if it's function prototype - if ( *nameStart == ')' ) - { - typeEnd = nameStart+1; + // skip argument list + while ( *nameStart != '(' ) --nameStart; - // skip argument list - while ( *nameStart != '(' ) --nameStart; + // skip to function type definition + while ( *nameStart != ')' ) --nameStart; - // skip to function type definition - while ( *nameStart != ')' ) --nameStart; - - skip_next_token_back( nameStart ); + skip_next_token_back( nameStart ); - nameEnd = nameStart; + nameEnd = nameStart; - skip_token_back( nameStart ); + skip_token_back( nameStart ); - if ( *nameStart == '*' ) ++nameStart; - } + if ( *nameStart == '*' ) ++nameStart; + } - get_string_between( start, typeEnd, &pTDef->mOriginalType ); + get_string_between( start, typeEnd, &pTDef->mOriginalType ); - get_string_between( nameStart, nameEnd, &pTDef->mName ); + get_string_between( nameStart, nameEnd, &pTDef->mName ); - clear_commets_queue(); + clear_commets_queue(); - restore_line_no( tmpLnNo ); + restore_line_no( tmpLnNo ); }