Author Topic: Is it possible for the parser to support newlib prototypes?  (Read 35750 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5247
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is it possible for the parser to support newlib prototypes?
« Reply #15 on: September 08, 2014, 04:22:01 pm »
...
I hope that is clear now.
Hi, Huki, thanks for the explanation, now I fully understand the idea of your patch. Especially the Case 3 and Case 4.
As a conclusion: Showing the call tip is very tricky. Sometimes, you get some text matched macro tokens, but those tokens don't have args. How can we show call tips for them? We just expand those tokens, the most important(final) step to collect the call tip information is that expansion should stop at a Token which has args.
Yeah, the args are the call tips. Thus, don't expand to much, since we may lose the args if we expand to much.  ;)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5247
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is it possible for the parser to support newlib prototypes?
« Reply #16 on: September 09, 2014, 04:28:42 pm »
When testing your patch, I found another bug in CC's call tip.
Code::Blocks / Tickets / #47 Show call tip of the constructor function
Call tip failed with or without your patch. So, let's leave it for another fix.  ;)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5247
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is it possible for the parser to support newlib prototypes?
« Reply #17 on: September 10, 2014, 04:55:25 am »
@Huki, your patch is in trunk now! Thanks for the contribution. I change some comments, fell free to comment.  ;D
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Huki

  • Multiple posting newcomer
  • *
  • Posts: 95
Re: Is it possible for the parser to support newlib prototypes?
« Reply #18 on: September 10, 2014, 04:52:13 pm »
Thanks for the commit.. and the comments. :)

When testing your patch, I found another bug in CC's call tip.
Code::Blocks / Tickets / #47 Show call tip of the constructor function
Call tip failed with or without your patch. So, let's leave it for another fix.  ;)
I get the bug with your test code. But curiously it works inside the CB project, see the attached screenshots: both types of constructor calltips work fine. I remember it was added recently by a patch from Alpha, I found the post where you mention it, see discussion here (at the end of the post).

EDIT: removed attachments.
« Last Edit: September 10, 2014, 05:34:06 pm by Huki »

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5247
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is it possible for the parser to support newlib prototypes?
« Reply #19 on: September 10, 2014, 05:05:32 pm »
Thanks for the commit.. and the comments. :)

When testing your patch, I found another bug in CC's call tip.
Code::Blocks / Tickets / #47 Show call tip of the constructor function
Call tip failed with or without your patch. So, let's leave it for another fix.  ;)
I get the bug with your test code. But curiously it works inside the CB project, see the attached screenshots: both types of constructor calltips work fine. I remember it was added recently by a patch from Alpha, I found the post where you mention it, see discussion here (at the end of the post).

Oh, I just found that the below test works OK for showing the call tip, see the "public" key word.
Code: [Select]
class AAA
{
public:
    AAA(int a){;}
    int m_b;
};


AAA(8);

 :D  :D
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Huki

  • Multiple posting newcomer
  • *
  • Posts: 95
Re: Is it possible for the parser to support newlib prototypes?
« Reply #20 on: September 10, 2014, 05:31:52 pm »
Oh, I just found that the below test works OK for showing the call tip, see the "public" key word.
Code: [Select]
class AAA
{
public:
    AAA(int a){;}
    int m_b;
};


AAA(8);

 :D  :D
Ahah.. :P Yep, that works for me too.


BTW, now I also tested my note about semi-colon:
Quote
I think Alpha's patch was trying to get calltips for:
Code: [Select]
wxStaticText static(|Though I'm not sure if it can work, because the variable "static" in the above code won't be parsed unless semi-colon is typed, right?
See the code in DoParse(): if we peek a "(" or a ";", we parse the variable.
Code: [Select]
               else if (   (peek == ParserConsts::semicolon)
                         || (   (   m_Options.useBuffer
                                 && (peek.GetChar(0) == ParserConsts::opbracket_chr) )
                             && (!m_Str.Contains(ParserConsts::dcolon)) ) )
                {
                    if (   !m_Str.IsEmpty()
                        && (    wxIsalpha(token.GetChar(0))
                            || (token.GetChar(0) == ParserConsts::underscore_chr) ) )
                    {
                        if (m_Options.handleVars)
                        {
                            Token* newToken = DoAddToken(tkVariable, token, m_Tokenizer.GetLineNumber());
                            if (newToken && !m_TemplateArgument.IsEmpty())
                                ResolveTemplateArgs(newToken);
                        }
                        else
                            SkipToOneOfChars(ParserConsts::semicolonclbrace, true, true);
                    }
                }

The current code is already checking for the opbracket, but there seem to be some problems:
Code: [Select]
class AAA
{
public:
    AAA(int a){;}
    int m_b;
};

AAA bbb( // I don't get the constructor calltip

EDIT: removed attachments.
« Last Edit: September 11, 2014, 07:10:09 am by Huki »

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: Is it possible for the parser to support newlib prototypes?
« Reply #21 on: September 10, 2014, 06:02:28 pm »
Oh, I just found that the below test works OK for showing the call tip, see the "public" key word.
Sorry, should I have mentioned earlier.  I filtered out non-visible ctors to avoid the annoying wxString(int) and similar (private ctors are almost never used, to my knowledge).

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5247
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is it possible for the parser to support newlib prototypes?
« Reply #22 on: September 11, 2014, 07:15:25 am »
The current code is already checking for the opbracket, but there seem to be some problems:
Code: [Select]
class AAA
{
public:
    AAA(int a){;}
    int m_b;
};

AAA bbb( // I don't get the constructor calltip

EDIT: removed attachments.


In my opinion, the "variable pattern" can only be recognized as: "AAA BBB;"  or "AAA BBB CCC" or "AAA BBB, CCC".
AAA, BBB, CCC are all kinds of lexeme.
But the pattern like "AAA BBB(...);" are recognized as functions.

If we see "AAA BBB(...)" we don't know it is a variable or a function. :) That's the reason of this call tip failure I think.
I will check the code now.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Huki

  • Multiple posting newcomer
  • *
  • Posts: 95
Re: Is it possible for the parser to support newlib prototypes?
« Reply #23 on: September 11, 2014, 07:21:13 am »
Oh, I just found that the below test works OK for showing the call tip, see the "public" key word.
Sorry, should I have mentioned earlier.  I filtered out non-visible ctors to avoid the annoying wxString(int) and similar (private ctors are almost never used, to my knowledge).
Yes, thanks, that should be the expected behavior too. I guess ollydbg and I were getting a little forgetful.. ;)


BTW, now I also tested my note about semi-colon:
[...]
Today I checked it and it's clear now. A code like AAA bbb(...) can be either a function declaration, or a class variable initialized with a constructor. So how do we find out which one it is? Technically the class variable won't have type info in the arguments, eg:
Code: [Select]
AAA bbb(int a); // function declaration
AAA bbb(a); // variable of class AAA

But our CC plugin follows a much simpler method: if the code is found in the global namespace, "handle_functions" is true, and it is parsed like a function declaration. Inside a local block, "handle_functions" is false and it is parsed like a variable. So with the current code we can get the calltip:
Code: [Select]
class AAA
{
public:
    AAA(int a){;}
    int m_b;
};

void func()
{
    AAA bbb( // shows calltip for constructor AAA::AAA()
}

It's probably enough for most purposes, so for now I'll leave it like this.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5247
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is it possible for the parser to support newlib prototypes?
« Reply #24 on: September 11, 2014, 07:27:07 am »
Oh, I just found that the below test works OK for showing the call tip, see the "public" key word.
Sorry, should I have mentioned earlier.  I filtered out non-visible ctors to avoid the annoying wxString(int) and similar (private ctors are almost never used, to my knowledge).
Yes, thanks, that should be the expected behavior too. I guess ollydbg and I were getting a little forgetful.. ;)
Yes, I can't remember anything about this.   ;)


Quote
BTW, now I also tested my note about semi-colon:
[...]
Today I checked it and it's clear now. A code like AAA bbb(...) can be either a function declaration, or a class variable initialized with a constructor. So how do we find out which one it is? Technically the class variable won't have type info in the arguments, eg:
Code: [Select]
AAA bbb(int a); // function declaration
AAA bbb(a); // variable of class AAA

But our CC plugin follows a much simpler method: if the code is found in the global namespace, "handle_functions" is true, and it is parsed like a function declaration. Inside a local block, "handle_functions" is false and it is parsed like a variable. So with the current code we can get the calltip:
Code: [Select]
class AAA
{
public:
    AAA(int a){;}
    int m_b;
};

void func()
{
    AAA bbb( // shows calltip for constructor AAA::AAA()
}

It's probably enough for most purposes, so for now I'll leave it like this.

Correct, I just review the code, and I get the same conclusion. It comes from this code:
Code: [Select]
  (peek == ParserConsts::semicolon)
                         || (   (   m_Options.useBuffer
                                 && (peek.GetChar(0) == ParserConsts::opbracket_chr) )
                             && (!m_Str.Contains(ParserConsts::dcolon)) ) )

m_Options.useBuffer means we are parsing function body, and peek.GetChar(0) == ParserConsts::opbracket_chr means we find a pattern like "AAA BBB(", so this is a variable only in function bodies. Not easy to handle those issue, since they need semantic information.

EDIT
I will add some comments about those patterns in the source code.
« Last Edit: September 11, 2014, 07:29:13 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Huki

  • Multiple posting newcomer
  • *
  • Posts: 95
Re: Is it possible for the parser to support newlib prototypes?
« Reply #25 on: September 11, 2014, 11:32:17 am »
I have looked at the patch for function pointers that I mentioned earlier:
I try to test this code with your patch:
Code: [Select]
void my_f(int b);

void (*foo)(int a);

foo = &my_f;

foo(5);

But I don't have tip info if the mouse hover on the "foo(5)".
Find declaration of "foo(5)" gives nothing.

I think normal function pointer variables parsing require another patch (I will send it next, but it requires some cleanup before).

Function pointers are handled just like normal functions, but of course, they only have a declaration, not definition. So I've updated HandleFunctions() to handle this as a special case.

This patch adds support for func ptr both in global and local block. Also, all the cases involving opbracket_chr are handled in one place, in this order:
Code: [Select]
void(*foo)(int a); // func ptr
void *(*foo)(int a); // func ptr with ptr return type
void foo(int a); // function decl
AAA foo(5); // var initialized with ctor (only supported for local block)

You can use your earlier test code (quoted above) to test this patch. Let me know if it's ok.
« Last Edit: September 11, 2014, 11:37:03 am by Huki »

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5247
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is it possible for the parser to support newlib prototypes?
« Reply #26 on: September 12, 2014, 04:15:54 am »
I have looked at the patch for function pointers that I mentioned earlier:
I try to test this code with your patch:
Code: [Select]
void my_f(int b);

void (*foo)(int a);

foo = &my_f;

foo(5);

But I don't have tip info if the mouse hover on the "foo(5)".
Find declaration of "foo(5)" gives nothing.

I think normal function pointer variables parsing require another patch (I will send it next, but it requires some cleanup before).

Function pointers are handled just like normal functions, but of course, they only have a declaration, not definition. So I've updated HandleFunctions() to handle this as a special case.

This patch adds support for func ptr both in global and local block. Also, all the cases involving opbracket_chr are handled in one place, in this order:
Code: [Select]
void(*foo)(int a); // func ptr
void *(*foo)(int a); // func ptr with ptr return type
void foo(int a); // function decl
AAA foo(5); // var initialized with ctor (only supported for local block)

You can use your earlier test code (quoted above) to test this patch. Let me know if it's ok.

Thanks, I reviewed and tested the patch, works fine, thanks! Here is my modified patch. (I just add some comments)
Code: [Select]
src/plugins/codecompletion/parser/parser.cpp       |   2 +-
 src/plugins/codecompletion/parser/parserthread.cpp | 101 +++++++++++++++++++--
 src/plugins/codecompletion/parser/parserthread.h   |   3 +-
 3 files changed, 94 insertions(+), 12 deletions(-)

diff --git a/src/plugins/codecompletion/parser/parser.cpp b/src/plugins/codecompletion/parser/parser.cpp
index feeec27..a7886bd 100644
--- a/src/plugins/codecompletion/parser/parser.cpp
+++ b/src/plugins/codecompletion/parser/parser.cpp
@@ -631,7 +631,7 @@ bool Parser::ParseBuffer(const wxString& buffer,   bool isLocal,
     opts.wantPreprocessor     = m_Options.wantPreprocessor;
     opts.parseComplexMacros   = false;
 
-    opts.handleFunctions      = false;
+    opts.handleFunctions      = true;   // enabled to support function ptr in local block
 
     opts.storeDocumentation   = m_Options.storeDocumentation;
 
diff --git a/src/plugins/codecompletion/parser/parserthread.cpp b/src/plugins/codecompletion/parser/parserthread.cpp
index d408270..5d5ab6c 100644
--- a/src/plugins/codecompletion/parser/parserthread.cpp
+++ b/src/plugins/codecompletion/parser/parserthread.cpp
@@ -1004,6 +1004,8 @@ void ParserThread::DoParse()
         }
         else if (!switchHandled)
         {
+            // since we can't recognize the pattern by token, then the token
+            // is normally an identifier style lexme, now we try to peek the next token
             wxString peek = m_Tokenizer.PeekToken();
             if (!peek.IsEmpty())
             {
@@ -1014,8 +1016,9 @@ void ParserThread::DoParse()
                     && m_EncounteredTypeNamespaces.empty()
                     && (!m_LastParent || m_LastParent->m_Name != token) ) // if func has same name as current scope (class)
                 {
+                    // pattern: AAA (...)
                     int id = m_TokenTree->TokenExists(token, -1, tkMacroDef);
-
+                    // if AAA is a macro definition, then expand this macro
                     if (id != -1)
                     {
                         HandleMacroExpansion(id, peek);
@@ -1023,17 +1026,31 @@ void ParserThread::DoParse()
                     }
                     else
                     {
+                        // see what is inside the (...)
                         wxString arg = m_Tokenizer.GetToken(); // eat args ()
+                        // try to see whether the peek pattern is (* BBB)
                         int pos = peek.find(ParserConsts::ptr);
                         if (pos != wxNOT_FOUND)
                         {
                             peek = m_Tokenizer.PeekToken();
                             if (peek.GetChar(0) == ParserConsts::opbracket_chr)
                             {
+                                // pattern: AAA (* BBB) (...)
+                                // where peek is (...) and arg is (* BBB)
                                 arg.Trim(true).RemoveLast();
                                 arg.Remove(0, pos+1);
-                                if (!m_Options.useBuffer || m_Options.bufferSkipBlocks)
-                                    HandleFunction(arg); // function
+                                arg.Trim(true).Trim(false);
+                                // NOTE: support func ptr in local block, show return type.
+                                // if (!m_Options.useBuffer || m_Options.bufferSkipBlocks)
+                                //     HandleFunction(arg); // function
+                                // AAA now becomes the last element of stacked type string
+                                // which is the return type of function ptr
+                                m_Str << token << ParserConsts::space_chr;
+                                // * BBB is now the function ptr's name
+                                HandleFunction(/*function name*/ arg,
+                                               /*isOperator*/    false,
+                                               /*isPointer*/     true);
+                                m_Str.Clear();
                             }
                         }
                         else // wxString arg = m_Tokenizer.GetToken(); // eat args ()
@@ -1042,10 +1059,50 @@ void ParserThread::DoParse()
                 }
                 else if (peek.GetChar(0) == ParserConsts::opbracket_chr && m_Options.handleFunctions)
                 {
-                    if (!m_Options.useBuffer || m_Options.bufferSkipBlocks)
+                    // NOTE: support some more cases..., such as m_Str is not empty
+                    // if (!m_Options.useBuffer || m_Options.bufferSkipBlocks)
+                    //     HandleFunction(token); // function
+                    // else
+                    //     m_Tokenizer.GetToken(); // eat args when parsing block
+
+                    // function ptr with pointer return type
+                    // eg: void *(*Alloc)(void *p, size_t size);
+                    // where, m_Str=void, token=(*Alloc), peek=(void *p, size_t size)
+                    if (   (m_LastToken == ParserConsts::ref_chr || m_LastToken == ParserConsts::ptr_chr) // (m_PointerOrRef)
+                        && (token.GetChar(0) == ParserConsts::opbracket_chr))
+                    {
+                        int pos = token.find(ParserConsts::ptr);
+                        if (pos != wxNOT_FOUND)
+                        {
+                            wxString arg = token;
+                            arg.Trim(true).RemoveLast();
+                            arg.Remove(0, pos+1);
+                            arg.Trim(true).Trim(false);
+                            HandleFunction(/*function name*/ arg,
+                                           /*isOperator*/    false,
+                                           /*isPointer*/     true);
+                        }
+                    }
+                    else if (!m_Options.useBuffer || m_Options.bufferSkipBlocks)
+                    {
+                        // pattern AAA BBB (...) in global namespace (not in local block)
+                        // so, this is mostly like a function declaration, but in-fact this
+                        // can also be a global variable initializized with ctor, but for
+                        // simplicity, we drop the later case
                         HandleFunction(token); // function
+                    }
                     else
+                    {
+                        // local variables initialized with ctor
+                        if (!m_Str.IsEmpty() && m_Options.handleVars)
+                        {
+                            Token* newToken = DoAddToken(tkVariable, token, m_Tokenizer.GetLineNumber());
+                            if (newToken && !m_TemplateArgument.IsEmpty())
+                                ResolveTemplateArgs(newToken);
+                        }
                         m_Tokenizer.GetToken(); // eat args when parsing block
+                    }
+
                     m_Str.Clear();
                 }
                 else if (   (peek  == ParserConsts::colon)
@@ -1113,15 +1170,15 @@ void ParserThread::DoParse()
                         m_EncounteredNamespaces.push(token);
                     m_Tokenizer.GetToken(); // eat ::
                 }
-                else if (   (peek == ParserConsts::semicolon)
-                         || (   (   m_Options.useBuffer
-                                 && (peek.GetChar(0) == ParserConsts::opbracket_chr) )
-                             && (!m_Str.Contains(ParserConsts::dcolon)) ) )
+                // NOTE: opbracket_chr already handled above
+                else if (peek==ParserConsts::semicolon)
                 {
                     if (   !m_Str.IsEmpty()
                         && (    wxIsalpha(token.GetChar(0))
                             || (token.GetChar(0) == ParserConsts::underscore_chr) ) )
                     {
+                        // pattern: m_Str AAA;
+                        // where AAA is the variable name, m_Str contains type string
                         if (m_Options.handleVars)
                         {
                             Token* newToken = DoAddToken(tkVariable, token, m_Tokenizer.GetLineNumber());
@@ -1597,7 +1654,7 @@ void ParserThread::HandleDefines()
     wxString para; // function-like macro's args
     if (!readToEOL.IsEmpty())
     {
-        // a '(' char follow the macro name (without space between them) is regard as a
+        // a '(' char follow the macro name (without space between them) is regard as a
         // function like macro definition
         if (readToEOL[0] == ParserConsts::opbracket_chr) // function-like macro definition
         {
@@ -2091,7 +2148,7 @@ void ParserThread::HandleClass(EClassType ct)
     m_Tokenizer.SetState(oldState);
 }
 
-void ParserThread::HandleFunction(const wxString& name, bool isOperator)
+void ParserThread::HandleFunction(const wxString& name, bool isOperator, bool isPointer)
 {
     TRACE(_T("HandleFunction() : Adding function '")+name+_T("': m_Str='")+m_Str+_T("'"));
     int lineNr = m_Tokenizer.GetLineNumber();
@@ -2099,6 +2156,30 @@ void ParserThread::HandleFunction(const wxString& name, bool isOperator)
     wxString peek = m_Tokenizer.PeekToken();
     TRACE(_T("HandleFunction() : name='")+name+_T("', args='")+args+_T("', peek='")+peek+_T("'"));
 
+    // special case for function pointers
+    if (isPointer)
+    {
+        // pattern: m_Str AAA (*BBB) (...);
+        if (peek == ParserConsts::semicolon)
+        {
+            TRACE(_T("HandleFunction() : Add token name='")+name+_T("', args='")+args+_T("', return type='") + m_Str+ _T("'"));
+            Token* newToken =  DoAddToken(tkFunction, name, lineNr, 0, 0, args);
+            if (newToken)
+            {
+                newToken->m_IsConst = false;
+                newToken->m_TemplateArgument = m_TemplateArgument;
+                if (!m_TemplateArgument.IsEmpty() && newToken->m_TemplateMap.empty())
+                    ResolveTemplateArgs(newToken);
+            }
+            else
+            {
+                TRACE(_T("HandleFunction() : Unable to create/add new token: ") + name);
+            }
+            m_TemplateArgument.Clear();
+        }
+        return;
+    }
+
     if (!m_Str.StartsWith(ParserConsts::kw_friend))
     {
         int lineStart = 0;
diff --git a/src/plugins/codecompletion/parser/parserthread.h b/src/plugins/codecompletion/parser/parserthread.h
index d81b752..7421177 100644
--- a/src/plugins/codecompletion/parser/parserthread.h
+++ b/src/plugins/codecompletion/parser/parserthread.h
@@ -200,8 +200,9 @@ protected:
     /** handle function declaration or definition
       * @param name function name
       * @param isOperator if true, means it is an operator overload function
+      * @param isPointer if true, means it is a function pointer
       */
-    void HandleFunction(const wxString& name, bool isOperator = false);
+    void HandleFunction(const wxString& name, bool isOperator = false, bool isPointer = false);
 
     /** parse for loop arguments:
       * for(int X; ... ; ...)


If you are OK,  I'm going to commit.

BTW: by the way, maybe, the two condition:

Code: [Select]
                if (   (peek.GetChar(0) == ParserConsts::opbracket_chr)
                    && m_Options.handleFunctions
                    && m_Str.IsEmpty()
                    && m_EncounteredNamespaces.empty()
                    && m_EncounteredTypeNamespaces.empty()
                    && (!m_LastParent || m_LastParent->m_Name != token) )
                {
                       Handle pattern AAA(...)
                       -> maybe, it is a macro usage
                       -> maybe, it is a function ptr
                }

Code: [Select]
                else if (peek.GetChar(0) == ParserConsts::opbracket_chr && m_Options.handleFunctions)
                {
                       Handle pattern CCC::DDD  EEE::AAA(...)
                       or                  CCC::DDD* EEE::AAA(...)
                       -> maybe, it is a function declaration
                       -> maybe, it is a function ptr
                       -> maybe, it is a local variable initialization with ctor
                }
Those two conditions can be merged or some refactored, but I'm not quite sure. E.g. extract the handling macro usage, and merge handling of function decl or function ptr in one condition. This can be a new commit.  :D

BTW2: coding style: when adding comment, I think "// NOTE" is better, there is a space after "//".


If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Huki

  • Multiple posting newcomer
  • *
  • Posts: 95
Re: Is it possible for the parser to support newlib prototypes?
« Reply #27 on: September 12, 2014, 03:01:55 pm »
Ok about the patch, so feel free to commit. :)

Quote
BTW2: coding style: when adding comment, I think "// NOTE" is better, there is a space after "//".
Ok about that too.

BTW: by the way, maybe, the two condition:
[...]
Those two conditions can be merged or some refactored, but I'm not quite sure. E.g. extract the handling macro usage, and merge handling of function decl or function ptr in one condition. This can be a new commit.  :D
I agree we can separate the macro handling and merge the function handling.
We can think about supporting more cases for macro handling too. We currently handle function-like macros, and only when m_Str is empty, eg:
Code: [Select]
some code;
MACRO(); // expand this
more code;
Sometimes the macro is not the first token in the line, so m_Str is non-empty, just like the bug reported by the original poster in this thread:
Code: [Select]
FILE * _EXFUN(fopen, (const char *__restrict _name, const char *__restrict _type));Those can be handled.. and also variable-like macros..

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5247
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is it possible for the parser to support newlib prototypes?
« Reply #28 on: September 12, 2014, 04:38:16 pm »
Ok about the patch, so feel free to commit. :)
Done. rev 9916, thanks!


Quote
BTW: by the way, maybe, the two condition:
[...]
Those two conditions can be merged or some refactored, but I'm not quite sure. E.g. extract the handling macro usage, and merge handling of function decl or function ptr in one condition. This can be a new commit.  :D
I agree we can separate the macro handling and merge the function handling.
We can think about supporting more cases for macro handling too. We currently handle function-like macros, and only when m_Str is empty, eg:
Code: [Select]
some code;
MACRO(); // expand this
more code;
Sometimes the macro is not the first token in the line, so m_Str is non-empty, just like the bug reported by the original poster in this thread:
Code: [Select]
FILE * _EXFUN(fopen, (const char *__restrict _name, const char *__restrict _type));Those can be handled.. and also variable-like macros..
Good catch, though it will increase the parsing time, but I think it is worthy. This can remove my own hack on the user defined macro replacement rule.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline White-Tiger

  • Multiple posting newcomer
  • *
  • Posts: 83
Re: Is it possible for the parser to support newlib prototypes?
« Reply #29 on: September 14, 2014, 12:23:03 pm »
Yay! for the function pointer patch xD It finally works^^ (ok didn't test it, but I'm using them in different projects and they didn't work most of the time..)
It's weird though.. I've thought Code::Blocks was able to handle them as they sometimes seemed to work.. just didn't most of the time :P
Windoze 8.1 x86_64 16GiB RAM, wxWidgets-2.8x (latest,trunk), MinGW-builds (latest, posix-threads)
Code::Blocks (x86 , latest , selection length patch , build option fixes/additions , toggle comments)