Correctly parse function macros
Parse function macros and add it's list of arguments to the Macro definition. Change-Id: Id22f5cf4a1c098f7b4f5b72f002900cd40d03e0f Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
parent
34a3b63dc7
commit
38f1b4eeae
@ -452,9 +452,10 @@ static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode m
|
||||
|
||||
if (mode == PrepareDefine) {
|
||||
symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
|
||||
// make sure we explicitly add the whitespace here, so we can distinguish
|
||||
// correctly between regular and function macros
|
||||
if (is_space(*data))
|
||||
// make sure we explicitly add the whitespace here if the next char
|
||||
// is not an opening brace, so we can distinguish correctly between
|
||||
// regular and function macros
|
||||
if (*data != '(')
|
||||
symbols += Symbol(lineNum, WHITESPACE);
|
||||
mode = TokenizeDefine;
|
||||
continue;
|
||||
@ -536,14 +537,13 @@ void Preprocessor::macroExpandIdentifier(const Symbol &s, Symbols &preprocessed,
|
||||
return;
|
||||
}
|
||||
|
||||
Symbols expanded = macros.value(s).symbols;
|
||||
const Macro ¯o = macros.value(s);
|
||||
|
||||
// don't expand macros with arguments for now
|
||||
if (expanded.size() && expanded.at(0).token == PP_LPAREN) {
|
||||
preprocessed += s;
|
||||
if (macro.isFunction)
|
||||
return;
|
||||
}
|
||||
|
||||
Symbols expanded = macro.symbols;
|
||||
for (int i = 0; i < expanded.size(); ++i) {
|
||||
expanded[i].lineNum = s.lineNum;
|
||||
if (expanded.at(i).token == PP_IDENTIFIER)
|
||||
@ -906,9 +906,20 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
|
||||
{
|
||||
next(IDENTIFIER);
|
||||
QByteArray name = lexem();
|
||||
Macro macro;
|
||||
macro.isVariadic = false;
|
||||
Token t = next();
|
||||
if (t == LPAREN) {
|
||||
// we have a function macro
|
||||
macro.isFunction = true;
|
||||
parseDefineArguments(¯o);
|
||||
} else if (t == PP_WHITESPACE){
|
||||
macro.isFunction = false;
|
||||
} else {
|
||||
error("Moc: internal error");
|
||||
}
|
||||
int start = index;
|
||||
until(PP_NEWLINE);
|
||||
Macro macro;
|
||||
macro.symbols.reserve(index - start - 1);
|
||||
for (int i = start; i < index - 1; ++i)
|
||||
macro.symbols += symbols.at(i);
|
||||
@ -1012,6 +1023,46 @@ Symbols Preprocessor::preprocessed(const QByteArray &filename, QIODevice *file)
|
||||
return result;
|
||||
}
|
||||
|
||||
void Preprocessor::parseDefineArguments(Macro *m)
|
||||
{
|
||||
Symbols arguments;
|
||||
while (hasNext()) {
|
||||
Token t = next();
|
||||
if (t == PP_WHITESPACE)
|
||||
t = next();
|
||||
if (t == PP_RPAREN)
|
||||
break;
|
||||
if (t != PP_IDENTIFIER) {
|
||||
QByteArray l = lexem();
|
||||
if (l == "...") {
|
||||
m->isVariadic = true;
|
||||
arguments += symbol();
|
||||
while (test(PP_WHITESPACE));
|
||||
if (!test(PP_RPAREN))
|
||||
error("missing ')' in macro argument list");
|
||||
break;
|
||||
} else if (!is_identifier(l.constData(), l.length())) {
|
||||
qDebug() << l;
|
||||
error("Unexpected character in macro argument list.");
|
||||
}
|
||||
}
|
||||
|
||||
Symbol arg = symbol();
|
||||
if (arguments.contains(arg))
|
||||
error("Duplicate macro parameter.");
|
||||
arguments += symbol();
|
||||
|
||||
t = next();
|
||||
while (t == PP_WHITESPACE)
|
||||
t = next();
|
||||
if (t == PP_RPAREN)
|
||||
break;
|
||||
if (t != PP_COMMA)
|
||||
error("Unexpected character in macro argument list.");
|
||||
}
|
||||
m->arguments = arguments;
|
||||
}
|
||||
|
||||
void Preprocessor::until(Token t)
|
||||
{
|
||||
while(hasNext() && next() != t)
|
||||
|
@ -51,6 +51,9 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
struct Macro
|
||||
{
|
||||
bool isFunction;
|
||||
bool isVariadic;
|
||||
Symbols arguments;
|
||||
Symbols symbols;
|
||||
};
|
||||
|
||||
@ -75,6 +78,7 @@ public:
|
||||
Symbols preprocessed(const QByteArray &filename, FILE *file);
|
||||
Symbols preprocessed(const QByteArray &filename, QIODevice *device);
|
||||
|
||||
void parseDefineArguments(Macro *m);
|
||||
|
||||
void skipUntilEndif();
|
||||
bool skipBranch();
|
||||
|
@ -73,6 +73,18 @@ inline bool is_ident_char(char s)
|
||||
);
|
||||
}
|
||||
|
||||
inline bool is_identifier(const char *s, int len)
|
||||
{
|
||||
if (len < 1)
|
||||
return false;
|
||||
if (!is_ident_start(*s))
|
||||
return false;
|
||||
for (int i = 1; i < len; ++i)
|
||||
if (!is_ident_char(s[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool is_digit_char(char s)
|
||||
{
|
||||
return (s >= '0' && s <= '9');
|
||||
|
Loading…
Reference in New Issue
Block a user