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

📄 preprocessor.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the tools applications of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "preprocessor.h"#include "utils.h"#include "ppkeywords.cpp"#include <QStringList>#include <QFile>#include <QDir>#include <QFileInfo>QList<QByteArray> Preprocessor::includes;Macros Preprocessor::macros;bool Preprocessor::onlyPreprocess = false;QByteArray Preprocessor::protocol;QSet<QByteArray> Preprocessor::preprocessedIncludes;static inline bool hasNext(const Symbols &symbols, int i){ return (i < symbols.size()); }static inline const Symbol &next(const Symbols &symbols, int &i){ return symbols.at(i++); }static void skipUntilEndif(const Symbols &symbols, int &i){    while(i < symbols.size() - 1 && symbols.at(i).pp_token != PP_ENDIF){        switch (symbols.at(i).pp_token) {        case PP_IF:        case PP_IFDEF:        case PP_IFNDEF:            ++i;            skipUntilEndif(symbols, i);            break;        default:            ;        }        ++i;    }}static bool skipBranch(const Symbols &symbols, int &i){    while(i < symbols.size() - 1          && (symbols.at(i).pp_token != PP_ENDIF               && symbols.at(i).pp_token != PP_ELIF               && symbols.at(i).pp_token != PP_ELSE)       ){        switch (symbols.at(i).pp_token) {        case PP_IF:        case PP_IFDEF:        case PP_IFNDEF:            ++i;            skipUntilEndif(symbols, i);            break;        default:            ;        }        ++i;    }    return (i < symbols.size() - 1);}static QByteArray cleaned(const QByteArray &input){    QByteArray result;    result.reserve(input.size());    const char *data = input;    char *output = result.data();    int newlines = 0;    while (*data) {        while (*data && is_space(*data))            ++data;        bool takeLine = (*data == '#');        if (*data == '%' && *(data+1) == ':') {            takeLine = true;            ++data;        }        if (takeLine) {            *output = '#';            ++output;            do ++data; while (*data && is_space(*data));        }        while (*data) {            if (*data == '\\' && *(data+1) == '\n') {                ++newlines;                data += 2;                continue;            }            *output = *data;            ++output;            if (*data == '\n') {                while (newlines) {                    *output = '\n';                    ++output;                    --newlines;                }                ++data;                break;            }            ++data;        }    }    result.resize(output - result.constData());    return result;}enum TokenizeMode { TokenizeFile, TokenizeLine };static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeFile){    Symbols symbols;    const char *begin = input;    const char *data = begin;    while (*data) {        const char *lexem = data;        int state = 0;        PP_Token token = PP_NOTOKEN;        for (;;) {            if (static_cast<signed char>(*data) < 0) {                ++data;                continue;            }            int nextindex = pp_keywords[state].next;            int next = 0;            if (*data == pp_keywords[state].defchar)                next = pp_keywords[state].defnext;            else if (!state || nextindex)                    next = pp_keyword_trans[nextindex][(int)*data];            if (!next)                break;            state = next;            token = pp_keywords[state].token;            ++data;        }        // suboptimal, is_ident_char  should use a table        if (pp_keywords[state].ident && is_ident_char(*data))            token = pp_keywords[state].ident;        switch (token) {        case NOTOKEN:            ++data;            break;        case PP_IFDEF:            symbols += Symbol(lineNum, PP_IF, QByteArray());            symbols += Symbol(lineNum, PP_DEFINED, QByteArray());            continue;        case PP_IFNDEF:            symbols += Symbol(lineNum, PP_IF, QByteArray());            symbols += Symbol(lineNum, PP_NOT, QByteArray());            symbols += Symbol(lineNum, PP_DEFINED, QByteArray());            continue;        case PP_QUOTE:            data = skipQuote(data);            token = PP_STRING_LITERAL;            break;        case PP_SINGLEQUOTE:            while (*data && (*data != '\''                             || (*(data-1)=='\\'                                  && *(data-2)!='\\')))                ++data;            if (*data)                ++data;            token = PP_CHARACTER_LITERAL;            break;        case PP_DIGIT:            while (is_digit_char(*data))                ++data;            if (!*data || *data != '.') {                token = PP_INTEGER_LITERAL;                if (data - lexem == 1 &&                     (*data == 'x' || *data == 'X')                     && *lexem == '0') {                    ++data;                    while (is_hex_char(*data))                        ++data;                }                break;            }            token = PP_FLOATING_LITERAL;            ++data;            // fall through        case PP_FLOATING_LITERAL:            while (is_digit_char(*data))                ++data;            if (*data == '+' || *data == '-')                ++data;            if (*data == 'e' || *data == 'E') {                ++data;                while (is_digit_char(*data))                    ++data;            }            if (*data == 'f' || *data == 'F'                || *data == 'l' || *data == 'L')                ++data;            break;        case PP_CHARACTER:            while (is_ident_char(*data))                ++data;            token = PP_IDENTIFIER;            break;        case PP_C_COMMENT:            while (*data && (*(data-1) != '/' || *(data-2) != '*')) {                if (*data == '\n')                    ++lineNum;                ++data;            }            token = PP_WHITESPACE; // one comment, one whitespace            // fall through;        case PP_WHITESPACE:            while (*data && (*data == ' ' || *data == '\t'))                ++data;            break;        case PP_CPP_COMMENT:            while (*data && *data != '\n')                ++data;            continue; // ignore safly, the newline is a seperator        case PP_NEWLINE:            if (mode == TokenizeLine)                goto exit;            ++lineNum;            break;        default:            break;        }        symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);    }exit:    symbols += Symbol(); // eof symbol    return symbols;}//static Symbols tokenize(const Symbol &symbol)//{ return tokenize(symbol.lexem(), symbol.lineNum, TokenizeLine); }static Symbols substitute(const Macros &macros, const Symbols& symbols, int &i,                          bool discardWhitespace = false, QList<QByteArray> safeset = QList<QByteArray>()){    QByteArray lexem = symbols.at(i-1).lexem();    if (!macros.contains(lexem) || safeset.contains(lexem))        return Symbols(1, symbols.at(i-1));    QByteArray macro = macros.value(lexem);                       // ### cannot do parameters yet, TODO    if (macro.size() && macro.at(0) == '(')        return Symbols(1, symbols.at(i-1));    safeset += lexem;    Symbols syms = tokenize(macro, symbols.at(i-1).lineNum, TokenizeLine);    Symbols result;    int j = 0;    bool skip = false;    while (hasNext(syms, j+1)) {        const Symbol &sym = next(syms, j);        if (discardWhitespace && sym.pp_token == PP_WHITESPACE)            continue;        if (sym.pp_token == PP_IDENTIFIER && !skip)            result += substitute(macros, syms, j, discardWhitespace, safeset);        else            result += sym;        skip = (sym.pp_token == PP_DEFINED || skip && sym.pp_token == PP_LPAREN);    }    return result;}struct PP_Expression{    PP_Expression():i(0){}    Macros macros;    Symbols symbols;    int i;    int value() { i = 0; return unary_expression_lookup() ?  conditional_expression() : 0; }    inline bool hasNext() const { return (i <= symbols.size()); }    inline PP_Token next() { return symbols.at(i++).pp_token; }    bool test(PP_Token);    inline void prev() {--i;}    PP_Token lookup(int k = 1);    inline PP_Token token() { return symbols.at(i-1).pp_token;}    inline QByteArray lexem() { return symbols.at(i-1).lexem();}    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();};inline bool PP_Expression::test(PP_Token token){    if (i < symbols.size() && symbols.at(i).pp_token == token) {        ++i;        return true;    }    return false;}inline PP_Token PP_Expression::lookup(int k){    const int l = i - 1 + k;    return l < symbols.size() ? symbols.at(l).pp_token : PP_NOTOKEN;}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:

⌨️ 快捷键说明

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