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

📄 preprocessor.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 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://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** 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 "keywords.cpp"#include "ppkeywords.cpp"#include <QStringList>#include <QFile>#include <QDir>#include <QFileInfo>// transform \r\n into \n// \r into \n (os9 style)// backslash-newlines into newlinesstatic 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) {            // handle \\\n, \\\r\n and \\\r            if (*data == '\\') {                if (*(data + 1) == '\r') {                    ++data;                }                if (*data && (*(data + 1) == '\n' || (*data) == '\r')) {                    ++newlines;                    data += 1;                    if (*data != '\r')                        data += 1;                    continue;                }            } else if (*data == '\r' && *(data + 1) == '\n') { // reduce \r\n to \n                ++data;            }            char ch = *data;            if (ch == '\r') // os9: replace \r with \n                ch = '\n';            *output = ch;            ++output;            if (*data == '\n') {                // output additional newlines to keep the correct line-numbering                // for the lines following the backslash-newline sequence(s)                while (newlines) {                    *output = '\n';                    ++output;                    --newlines;                }                ++data;                break;            }            ++data;        }    }    result.resize(output - result.constData());    return result;}bool Preprocessor::preprocessOnly = false;void Preprocessor::skipUntilEndif(){    while(index < symbols.size() - 1 && symbols.at(index).token != PP_ENDIF){        switch (symbols.at(index).token) {        case PP_IF:        case PP_IFDEF:        case PP_IFNDEF:            ++index;            skipUntilEndif();            break;        default:            ;        }        ++index;    }}bool Preprocessor::skipBranch(){    while (index < symbols.size() - 1          && (symbols.at(index).token != PP_ENDIF               && symbols.at(index).token != PP_ELIF               && symbols.at(index).token != PP_ELSE)       ){        switch (symbols.at(index).token) {        case PP_IF:        case PP_IFDEF:        case PP_IFNDEF:            ++index;            skipUntilEndif();            break;        default:            ;        }        ++index;    }    return (index < symbols.size() - 1);}enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude };static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeCpp){    Symbols symbols;    const char *begin = input;    const char *data = begin;    while (*data) {        if (mode == TokenizeCpp) {            int column = 0;            const char *lexem = data;            int state = 0;            Token token = NOTOKEN;            for (;;) {                if (static_cast<signed char>(*data) < 0) {                    ++data;                    continue;                }                int nextindex = keywords[state].next;                int next = 0;                if (*data == keywords[state].defchar)                    next = keywords[state].defnext;                else if (!state || nextindex)                    next = keyword_trans[nextindex][(int)*data];                if (!next)                    break;                state = next;                token = keywords[state].token;                ++data;            }            // suboptimal, is_ident_char  should use a table            if (keywords[state].ident && is_ident_char(*data))                token = keywords[state].ident;            if (token == NOTOKEN) {                // an error really                ++data;                continue;            }            ++column;            if (token > SPECIAL_TREATMENT_MARK) {                switch (token) {                case QUOTE:                    data = skipQuote(data);                    token = STRING_LITERAL;                    // concatenate multi-line strings for easier                    // STRING_LITERAAL handling in moc                    if (!Preprocessor::preprocessOnly                        && !symbols.isEmpty()                        && symbols.last().token == STRING_LITERAL) {                        QByteArray newString = symbols.last().unquotedLexem();                        newString += input.mid(lexem - begin + 1, data - lexem - 2);                        newString.prepend('\"');                        newString.append('\"');                        symbols.last() = Symbol(symbols.last().lineNum,                                                STRING_LITERAL,                                                newString);                        continue;                    }                    break;                case SINGLEQUOTE:                    while (*data && (*data != '\''                                     || (*(data-1)=='\\'                                         && *(data-2)!='\\')))                        ++data;                    if (*data)                        ++data;                    token = CHARACTER_LITERAL;                    break;                case DIGIT:                    while (is_digit_char(*data))                        ++data;                    if (!*data || *data != '.') {                        token = INTEGER_LITERAL;                        if (data - lexem == 1 &&                            (*data == 'x' || *data == 'X')                            && *lexem == '0') {                            ++data;                            while (is_hex_char(*data))                                ++data;                        }                        break;                    }                    token = FLOATING_LITERAL;                    ++data;                    // fall through                case 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 HASH:                    if (column == 1) {                        mode = PreparePreprocessorStatement;                        while (*data && (*data == ' ' || *data == '\t'))                            ++data;                        if (is_ident_char(*data))                            mode = TokenizePreprocessorStatement;                        continue;                    }                    break;                case NEWLINE:                    ++lineNum;                    continue;                case BACKSLASH:                {                    const char *rewind = data;                    while (*data && (*data == ' ' || *data == '\t'))                        ++data;                    if (*data && *data == '\n') {                        ++data;                        continue;                    }                    data = rewind;                } break;                case CHARACTER:                    while (is_ident_char(*data))                        ++data;                    token = IDENTIFIER;                    break;                case C_COMMENT:                    while (*data && (*(data-1) != '/' || *(data-2) != '*')) {                        if (*data == '\n')                            ++lineNum;                        ++data;                    }                    token = WHITESPACE; // one comment, one whitespace                    // fall through;                case WHITESPACE:                    if (column == 1)                        column = 0;                    while (*data && (*data == ' ' || *data == '\t'))                        ++data;                    if (Preprocessor::preprocessOnly) // tokenize whitespace                        break;                    continue;                case CPP_COMMENT:                    while (*data && *data != '\n')                        ++data;                    continue; // ignore safely, the newline is a separator                default:                    continue; //ignore                }            }#ifdef USE_LEXEM_STORE            if (!Preprocessor::preprocessOnly                && token != IDENTIFIER                && token != STRING_LITERAL                && token != FLOATING_LITERAL                && token != INTEGER_LITERAL)                symbols += Symbol(lineNum, token);            else#endif                symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);        } else { //   Preprocessor            const char *lexem = data;            int state = 0;            Token token = NOTOKEN;            if (mode == TokenizePreprocessorStatement) {                state = pp_keyword_trans[0][(int)'#'];                mode = TokenizePreprocessor;            }            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);                symbols += Symbol(lineNum, PP_DEFINED);                continue;            case PP_IFNDEF:                symbols += Symbol(lineNum, PP_IF);                symbols += Symbol(lineNum, PP_NOT);                symbols += Symbol(lineNum, PP_DEFINED);                continue;            case PP_INCLUDE:                mode = TokenizeInclude;                break;            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:                if (mode == PreparePreprocessorStatement) {                    // rewind entire token to begin                    data = lexem;                    mode = TokenizePreprocessorStatement;                    continue;                }                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;                continue; // the preprocessor needs no whitespace            case PP_CPP_COMMENT:                while (*data && *data != '\n')                    ++data;                continue; // ignore safely, the newline is a separator            case PP_NEWLINE:                ++lineNum;                mode = TokenizeCpp;                break;            case PP_BACKSLASH:            {                const char *rewind = data;                while (*data && (*data == ' ' || *data == '\t'))                    ++data;                if (*data && *data == '\n') {                    ++data;                    continue;                }                data = rewind;            } break;            case PP_LANGLE:                if (mode != TokenizeInclude)                    break;                token = PP_STRING_LITERAL;                while (*data && *data != '\n' && *(data-1) != '>')                    ++data;                break;            default:                break;            }            if (mode == PreparePreprocessorStatement)                continue;#ifdef USE_LEXEM_STORE            if (token != PP_IDENTIFIER                && token != PP_STRING_LITERAL                && token != PP_FLOATING_LITERAL                && token != PP_INTEGER_LITERAL)                symbols += Symbol(lineNum, token);

⌨️ 快捷键说明

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