⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 preprocessor.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        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_DEFINED:    {        QByteArray identifier;        if (test(PP_IDENTIFIER)) {            identifier = lexem();        } else if (test(PP_LPAREN)) {            if (test(PP_IDENTIFIER))                identifier = lexem();            test(PP_RPAREN);        }        return macros.contains(identifier);    }    default:        prev();        return primary_expression();    }}bool PP_Expression::unary_expression_lookup(){    PP_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 = QString(lexem()).toInt(0, 0);    }    return value;}bool PP_Expression::primary_expression_lookup(){    PP_Token t = lookup();    return (t == PP_IDENTIFIER            || t == PP_INTEGER_LITERAL            || t == PP_FLOATING_LITERAL            || t == PP_LPAREN);}static int evaluateCondition(const Macros &macros, const Symbols &symbols, int &i){    PP_Expression expression;    expression.macros = macros;    bool skip = false;    while (hasNext(symbols, i)) {        const Symbol &sym = next(symbols, i);        if (sym.pp_token == PP_WHITESPACE)            continue;        if (sym.pp_token == PP_IDENTIFIER && macros.contains(sym.lexem()) && !skip)            expression.symbols += substitute(macros, symbols, i, true);        else            expression.symbols += sym;        if (sym.pp_token == PP_NEWLINE)            break;        skip = (sym.pp_token == PP_DEFINED || skip && sym.pp_token == PP_LPAREN);    }    return expression.value();}static inline QByteArray lexemUntil(const Symbols &symbols, int i, PP_Token token){    QByteArray s;    while (i < symbols.size() && symbols.at(i).pp_token != token) {        s += symbols.at(i).lexem();        ++i;    }    return s;}static inline void until(const Symbols &symbols, int &i, PP_Token token){    while (i < symbols.size() && symbols.at(i).pp_token != token) {        ++i;    }}static void preprocess(const QByteArray &filename, const Symbols &symbols, Macros &macros, Symbols &preprocessed);static Symbols preprocess(const QByteArray &filename, const Symbols &symbols, Macros &macros){    Symbols preprocessed;    preprocess(filename, symbols, macros, preprocessed);    return preprocessed;}static void preprocess(const QByteArray &filename, const Symbols &symbols, Macros &macros, Symbols &preprocessed){    static int depth = 0;    preprocessed.reserve(preprocessed.size() + symbols.size());    int i = 0;    bool skipUntilNewLine = false;    while (hasNext(symbols,i)) {        if (skipUntilNewLine) {            until(symbols, i, PP_NEWLINE);            // skip the newline token            if (hasNext(symbols, i))                ++i;            skipUntilNewLine = false;            continue;        }        Symbol sym = next(symbols, i);        // preprocessor statements always end with a PP_NEWLINE. Some of the        // statement handlers operate on the actual lexical elements until the        // newline and others (like evaluationCondition) operate on the tokens        // directly. That's why we can't skip to PP_NEWLINE here but we have to        // do it in the next loop iteration, using skipUntilNewLine.        QByteArray statementLexem;        if (sym.pp_token >= PP_FIRST_STATEMENT            && sym.pp_token <= PP_LAST_STATEMENT) {            int lexemIndex = i;            if (hasNext(symbols, lexemIndex) && symbols.at(lexemIndex).pp_token == PP_WHITESPACE)                ++lexemIndex;            statementLexem = lexemUntil(symbols, lexemIndex, PP_NEWLINE);            skipUntilNewLine = true;        }        switch (sym.pp_token) {        case PP_INCLUDE:        {            QByteArray include = statementLexem;            const char *data = include.constData();            while (*data && is_whitespace(*data))                ++data;            const char *name = data++;            if (*name == '\"')                while (*data && *data != '\"')                    ++data;            else if (*name == '<')                while (*data && *data != '>')                    ++data;            else                continue;            bool local = (*name == '\"');            include = QByteArray(name + 1, data - name - 1);            // #### 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)                fi.setFile(QString::fromLocal8Bit(Preprocessor::includes.at(j)), QString::fromLocal8Bit(include));            if (!fi.exists())                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|QFile::Text))                continue;            if (Preprocessor::onlyPreprocess) {                Preprocessor::protocol += "#";                Preprocessor::protocol += QByteArray(depth * 2, ' ');                Preprocessor::protocol += "include \"";                Preprocessor::protocol += include;                Preprocessor::protocol += "\"\n";            }//            qDebug("... include %s", include.constData());            QByteArray input = file.readAll();            file.close();            if (input.isEmpty())                continue;            // phase 1: get rid of backslash-newlines            QByteArray phase1 = cleaned(input);            // phase 2: tokenize for the preprocessor            Symbols symbols = tokenize(phase1);            // phase 3: preprocess conditions and substitute macros            ++depth;            Symbol includeSym;            includeSym.lexem_data = "\n#moc_include_begin \"";            includeSym.lexem_data += include;            includeSym.lexem_data += "\"\n";            preprocessed += includeSym;            preprocess(include, symbols, macros, preprocessed);            includeSym.lexem_data = "\n#moc_include_end ";            includeSym.lexem_data += QByteArray::number(sym.lineNum);            includeSym.lineNum = sym.lineNum;            includeSym.pp_token = PP_MOC_INCLUDE_END;            preprocessed += includeSym;            --depth;            continue;        }        case PP_DEFINE:        {            QByteArray macro = statementLexem;            const char *data = macro.constData();            while (*data && is_whitespace(*data))                ++data;            if (!is_ident_start(*data))                continue;            const char *ident = data++;            while (*data && is_ident_char(*data))                ++data;            QByteArray name(ident, data - ident);            macros[name] = data;            if (Preprocessor::onlyPreprocess) {                Preprocessor::protocol += "#";                Preprocessor::protocol += QByteArray(depth * 2, ' ');                Preprocessor::protocol += "define ";                Preprocessor::protocol += name;                Preprocessor::protocol += "\n";            }            continue;        }        case PP_UNDEF: {            QByteArray macro = statementLexem;            const char *data = macro.constData();            while (*data && is_whitespace(*data))                ++data;            if (!is_ident_start(*data))                continue;            const char *ident = data++;            while (*data && is_ident_char(*data))                ++data;            QByteArray name(ident, data - ident);            macros.remove(name);            if (Preprocessor::onlyPreprocess) {                Preprocessor::protocol += "#";                Preprocessor::protocol += QByteArray(depth * 2, ' ');                Preprocessor::protocol += "undef ";                Preprocessor::protocol += name;                Preprocessor::protocol += "\n";            }            continue;        }        case PP_IDENTIFIER:            // 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_QT_SIGNALS:        case PP_QT_SLOTS:            if (macros.contains("QT_NO_KEYWORDS")) {                Symbol treatIdentSym;                treatIdentSym.lexem_data = "#moc_next_is_identifier ";                preprocessed += treatIdentSym;            }            break;        case PP_HASH:            continue; // skip unknown preprocessor statement        case PP_IFDEF:        case PP_IFNDEF:        case PP_IF:            while (!evaluateCondition(macros, symbols, i)) {                if (!skipBranch(symbols, i))                    break;                sym = next(symbols, i);                if (sym.pp_token != PP_ELIF)                    break;            }            // evaluateCondition already does the job of skipping            // over the newline, so don't do it twice and accidentially            // lose tokens by that            skipUntilNewLine = false;            continue;        case PP_ELIF:        case PP_ELSE:            skipUntilEndif(symbols, i);            // fall through        case PP_ENDIF:            continue;        default:            break;        }        preprocessed += sym;    }}QByteArray Preprocessor::preprocessed(const QByteArray &filename, FILE *file){    QByteArray output;    QFile qfile;    qfile.open(file, QFile::ReadOnly|QFile::Text);    QByteArray input = qfile.readAll();    if (input.isEmpty())        return output;    // phase 1: get rid of backslash-newlines    QByteArray phase1 = cleaned(input);    // phase 2: tokenize for the preprocessor    Symbols symbols = tokenize(phase1);#if 0    for (int j = 0; j < symbols.size(); ++j)        qDebug("line %d: %s(%d)",               symbols[j].lineNum,               symbols[j].lexem().constData(),               symbols[j].token);#endif    // phase 3: preprocess conditions and substitute macros    symbols = preprocess(filename, symbols, macros);    // final phase: compose string for the C++ scanner    int lineNum = 1;    PP_Token last = PP_NOTOKEN;    PP_Token secondlast = last;    int i = 0;    while (hasNext(symbols, i)) {        Symbol sym = next(symbols, i);        switch (sym.pp_token) {        case PP_NEWLINE:        case PP_WHITESPACE:            if (last != PP_WHITESPACE) {                secondlast = last;                last = PP_WHITESPACE;                output += ' ';            }            continue;        case PP_STRING_LITERAL:            if (last == PP_STRING_LITERAL)                output.chop(1);            else if (secondlast == PP_STRING_LITERAL && last == PP_WHITESPACE)                output.chop(2);            else                break;            output += sym.lexem().mid(1);            secondlast = last;            last = PP_STRING_LITERAL;            continue;        case PP_MOC_INCLUDE_END:            lineNum = sym.lineNum;            break;        default:            break;        }        secondlast = last;        last = sym.pp_token;        const int padding = sym.lineNum - lineNum;        if (padding > 0) {            output.resize(output.size() + padding);            qMemSet(output.data() + output.size() - padding, '\n', padding);            lineNum = sym.lineNum;        }        output += sym.lexem();    }    return output;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -