📄 preprocessor.cpp
字号:
else#endif symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem); } } symbols += Symbol(); // eof symbol return symbols;}void Preprocessor::substituteMacro(const MacroName ¯o, Symbols &substituted, MacroSafeSet safeset){ Symbols saveSymbols = symbols; int saveIndex = index; symbols = macros.value(macro).symbols; index = 0; safeset += macro; substituteUntilNewline(substituted, safeset); symbols = saveSymbols; index = saveIndex;}void Preprocessor::substituteUntilNewline(Symbols &substituted, MacroSafeSet safeset){ while (hasNext()) { Token token = next(); if (token == PP_IDENTIFIER) { MacroName macro = symbol(); if (macros.contains(macro) && !safeset.contains(macro)) { substituteMacro(macro, substituted, safeset); continue; } } else if (token == PP_DEFINED) { test(PP_LPAREN); next(PP_IDENTIFIER); Symbol definedOrNotDefined = symbol(); definedOrNotDefined.token = macros.contains(definedOrNotDefined)? PP_MOC_TRUE : PP_MOC_FALSE; substituted += definedOrNotDefined; test(PP_RPAREN); continue; } else if (token == PP_NEWLINE) { substituted += symbol(); break; } substituted += symbol(); }}class PP_Expression : public Parser{public: int value() { index = 0; return unary_expression_lookup() ? conditional_expression() : 0; } int conditional_expression(); int logical_OR_expression(); int logical_AND_expression(); int inclusive_OR_expression(); int exclusive_OR_expression(); int AND_expression(); int equality_expression(); int relational_expression(); int shift_expression(); int additive_expression(); int multiplicative_expression(); int unary_expression(); bool unary_expression_lookup(); int primary_expression(); bool primary_expression_lookup();};int PP_Expression::conditional_expression(){ int value = logical_OR_expression(); if (test(PP_QUESTION)) { int alt1 = conditional_expression(); int alt2 = test(PP_COLON) ? conditional_expression() : 0; return value ? alt1 : alt2; } return value;}int PP_Expression::logical_OR_expression(){ int value = logical_AND_expression(); if (test(PP_OROR)) return logical_OR_expression() || value; return value;}int PP_Expression::logical_AND_expression(){ int value = inclusive_OR_expression(); if (test(PP_ANDAND)) return logical_AND_expression() && value; return value;}int PP_Expression::inclusive_OR_expression(){ int value = exclusive_OR_expression(); if (test(PP_OR)) return value | inclusive_OR_expression(); return value;}int PP_Expression::exclusive_OR_expression(){ int value = AND_expression(); if (test(PP_HAT)) return value ^ exclusive_OR_expression(); return value;}int PP_Expression::AND_expression(){ int value = equality_expression(); if (test(PP_AND)) return value & AND_expression(); return value;}int PP_Expression::equality_expression(){ int value = relational_expression(); switch (next()) { case PP_EQEQ: return value == equality_expression(); case PP_NE: return value != equality_expression(); default: prev(); return value; }}int PP_Expression::relational_expression(){ int value = shift_expression(); switch (next()) { case PP_LANGLE: return value < relational_expression(); case PP_RANGLE: return value > relational_expression(); case PP_LE: return value <= relational_expression(); case PP_GE: return value >= relational_expression(); default: prev(); return value; }}int PP_Expression::shift_expression(){ int value = additive_expression(); switch (next()) { case PP_LTLT: return value << shift_expression(); case PP_GTGT: return value >> shift_expression(); default: prev(); return value; }}int PP_Expression::additive_expression(){ int value = multiplicative_expression(); switch (next()) { case PP_PLUS: return value + additive_expression(); case PP_MINUS: return value - additive_expression(); default: prev(); return value; }}int PP_Expression::multiplicative_expression(){ int value = unary_expression(); switch (next()) { case PP_STAR: return value * multiplicative_expression(); case PP_PERCENT: { int remainder = multiplicative_expression(); return remainder ? value % remainder : 0; } case PP_SLASH: { int div = multiplicative_expression(); return div ? value / div : 0; } default: prev(); return value; };}int PP_Expression::unary_expression(){ switch (next()) { case PP_PLUS: return unary_expression(); case PP_MINUS: return -unary_expression(); case PP_NOT: return !unary_expression(); case PP_TILDE: return ~unary_expression(); case PP_MOC_TRUE: return 1; case PP_MOC_FALSE: return 0; default: prev(); return primary_expression(); }}bool PP_Expression::unary_expression_lookup(){ Token t = lookup(); return (primary_expression_lookup() || t == PP_PLUS || t == PP_MINUS || t == PP_NOT || t == PP_TILDE || t == PP_DEFINED);}int PP_Expression::primary_expression(){ int value; if (test(PP_LPAREN)) { value = conditional_expression(); test(PP_RPAREN); } else { next(); value = lexem().toInt(0, 0); } return value;}bool PP_Expression::primary_expression_lookup(){ Token t = lookup(); return (t == PP_IDENTIFIER || t == PP_INTEGER_LITERAL || t == PP_FLOATING_LITERAL || t == PP_MOC_TRUE || t == PP_MOC_FALSE || t == PP_LPAREN);}int Preprocessor::evaluateCondition(){ PP_Expression expression; expression.currentFilenames = currentFilenames; substituteUntilNewline(expression.symbols); return expression.value();}void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed){ currentFilenames.push(filename); preprocessed.reserve(preprocessed.size() + symbols.size()); while (hasNext()) { Token token = next(); switch (token) { case PP_INCLUDE: { int lineNum = symbol().lineNum; QByteArray include; bool local = false; if (test(PP_STRING_LITERAL)) { local = lexem().startsWith('\"'); include = unquotedLexem(); } else continue; until(PP_NEWLINE); // #### stringery QFileInfo fi; if (local) fi.setFile(QFileInfo(QString::fromLocal8Bit(filename)).dir(), QString::fromLocal8Bit(include)); for (int j = 0; j < Preprocessor::includes.size() && !fi.exists(); ++j) { const IncludePath &p = Preprocessor::includes.at(j); if (p.isFrameworkPath) { const int slashPos = include.indexOf('/'); if (slashPos == -1) continue; QByteArray frameworkCandidate = include.left(slashPos); frameworkCandidate.append(".framework/Headers/"); fi.setFile(QString::fromLocal8Bit(p.path + "/" + frameworkCandidate), QString::fromLocal8Bit(include.mid(slashPos + 1))); } else { fi.setFile(QString::fromLocal8Bit(p.path), QString::fromLocal8Bit(include)); } } if (!fi.exists() || fi.isDir()) continue; include = fi.filePath().toLocal8Bit(); if (Preprocessor::preprocessedIncludes.contains(include)) continue; Preprocessor::preprocessedIncludes.insert(include); QFile file(QString::fromLocal8Bit(include)); if (!file.open(QFile::ReadOnly)) continue; QByteArray input = file.readAll(); file.close(); if (input.isEmpty()) continue; Symbols saveSymbols = symbols; int saveIndex = index; // phase 1: get rid of backslash-newlines input = cleaned(input); // phase 2: tokenize for the preprocessor symbols = tokenize(input); input.clear(); index = 0; // phase 3: preprocess conditions and substitute macros preprocessed += Symbol(0, MOC_INCLUDE_BEGIN, include); preprocess(include, preprocessed); preprocessed += Symbol(lineNum, MOC_INCLUDE_END, include); symbols = saveSymbols; index = saveIndex; continue; } case PP_DEFINE: { next(IDENTIFIER); QByteArray name = lexem(); 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); macros.insert(name, macro); continue; } case PP_UNDEF: { next(IDENTIFIER); QByteArray name = lexem(); until(PP_NEWLINE); macros.remove(name); continue; } case PP_IDENTIFIER: {// if (macros.contains(symbol()))// ; } // we _could_ easily substitute macros by the following // four lines, but we choose not to. /* if (macros.contains(sym.lexem())) { preprocessed += substitute(macros, symbols, i); continue; } */ break; case PP_HASH: until(PP_NEWLINE); continue; // skip unknown preprocessor statement case PP_IFDEF: case PP_IFNDEF: case PP_IF: while (!evaluateCondition()) { if (!skipBranch()) break; if (test(PP_ELIF)) { } else { until(PP_NEWLINE); break; } } continue; case PP_ELIF: case PP_ELSE: skipUntilEndif(); // fall through case PP_ENDIF: until(PP_NEWLINE); continue; case SIGNALS: case SLOTS: { Symbol sym = symbol(); if (macros.contains("QT_NO_KEYWORDS")) sym.token = IDENTIFIER; else sym.token = (token == SIGNALS ? Q_SIGNALS_TOKEN : Q_SLOTS_TOKEN); preprocessed += sym; } continue; default: break; } preprocessed += symbol(); } currentFilenames.pop();}Symbols Preprocessor::preprocessed(const QByteArray &filename, FILE *file){ QFile qfile; qfile.open(file, QFile::ReadOnly); QByteArray input = qfile.readAll(); if (input.isEmpty()) return symbols; // phase 1: get rid of backslash-newlines input = cleaned(input); // phase 2: tokenize for the preprocessor symbols = tokenize(input);#if 0 for (int j = 0; j < symbols.size(); ++j) fprintf(stderr, "line %d: %s(%s)\n", symbols[j].lineNum, symbols[j].lexem().constData(), tokenTypeName(symbols[j].token));#endif // phase 3: preprocess conditions and substitute macros Symbols result; preprocess(filename, result);#if 0 for (int j = 0; j < result.size(); ++j) fprintf(stderr, "line %d: %s(%s)\n", result[j].lineNum, result[j].lexem().constData(), tokenTypeName(result[j].token));#endif return result;}void Preprocessor::until(Token t){ while(hasNext() && next() != t) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -