I have noticed that there's some function prototypes in OpenCV code like below:
CVAPI (int ) cvAdd(XXXXX);
CVAPI (float) cvAdd2(XXXXX);
So, I add a replacement rule to deal with this kind of macro, this rule is really simple, I just add a '*' handling condition.
Here is the modified code, Tokenizer::MacroReplace function
wxString Tokenizer::MacroReplace(const wxString str)
{
ConfigManagerContainer::StringToStringMap::const_iterator it = s_Replacements.find(str);
if (it != s_Replacements.end())
{
// match one!
wxString key = it->first;
wxString value = it->second;
TRACE(_T("MacroReplace() : Replacing '%s' with rule '%s' (file='%s')."), key.wx_str(), value.wx_str(), m_Filename.wx_str());
if (value[0]=='+' && CurrentChar()=='(')
{
unsigned int start = m_TokenIndex;
m_Buffer[start] = ' ';
bool fillSpace = false;
while (m_Buffer[start]!=')')
{
if (m_Buffer[start]==',')
fillSpace = true;
if (fillSpace==true)
m_Buffer[start]=' ';
start++;
}
m_Buffer[start] = '{';
return value.Remove(0,1);
}
else if (value[0] == '-')
{
unsigned int lenKey = key.Len();
value = value.Remove(0,1);
unsigned int lenValue = value.Len();
for (unsigned int i=1; i<=lenKey; i++)
{
if (i < lenValue)
m_Buffer[m_TokenIndex-i] = value[lenValue-i];
else
m_Buffer[m_TokenIndex-i] = ' ';
}
int firstSpace = value.First(' ');
// adjust m_TokenIndex
m_TokenIndex = m_TokenIndex - lenValue + firstSpace;
return value.Mid(0,firstSpace);
}
else if (value[0] == '*')
{
wxString arg = m_Buffer.Mid(m_TokenIndex,15);
size_t left = arg.Find(_T('('));
size_t right= arg.Find(_T(')'));
if(left==wxNOT_FOUND||right==wxNOT_FOUND||left+2>right)
return value;
arg = arg.Mid(left+1,right-left-1);
arg.Trim(false);
arg.Trim(true);
m_TokenIndex = m_TokenIndex + right + 1;
TRACE(_T("MacroReplace() : Return %s, and move to '%s'"), arg.wx_str(), m_Buffer.Mid(m_TokenIndex,1).wc_str());
return arg;
}
else
return value;
}
return str;
}
Also, in the void ParserThread::DoParse() function body, I think it is the time to enable macro handing, (change it to
true in the if condition:
if (true /* TODO: Handle Macro detection properly */)
{
HandleMacro(token, peek);
m_Tokenizer.GetToken();
m_Str.Clear();
}
else
{
wxString arg = m_Tokenizer.GetToken(); // eat args ()
m_Str = token+arg;
}
So, we can parsing these kind of statement containing Macros like:
EVT_MENU(idMenuJumpToDeclaration, ClassBrowser::OnJumpTo)
EVT_MENU(idMenuJumpToImplementation, ClassBrowser::OnJumpTo)
EVT_MENU(idMenuRefreshTree, ClassBrowser::OnRefreshTree)
EVT_MENU(idMenuForceReparse, ClassBrowser::OnForceReparse)
I have tested the new enhancement in our parserTest project and an OpenCV project and CB project, it works fine.