From 38f1b4eeaeb013983126c155a9b25e08074c41f7 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 8 Sep 2012 21:44:12 +0200 Subject: 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 --- src/tools/moc/preprocessor.cpp | 67 +++++++++++++++++++++++++++++++++++++----- src/tools/moc/preprocessor.h | 4 +++ src/tools/moc/utils.h | 12 ++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index 4d4b571742..3c43974e2c 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -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) diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h index 70121c2102..518ead8b41 100644 --- a/src/tools/moc/preprocessor.h +++ b/src/tools/moc/preprocessor.h @@ -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(); diff --git a/src/tools/moc/utils.h b/src/tools/moc/utils.h index bacc908be2..aaaaaa3267 100644 --- a/src/tools/moc/utils.h +++ b/src/tools/moc/utils.h @@ -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'); -- cgit v1.2.3