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

📄 preprocessor.cpp

📁 cppcheck is a static C/C++ code analyzer that checks for memory leaks, mismatching allocation-deallo
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        }        if (line.find("#file \"") == 0 ||            line.find("#endfile") == 0)        {            // We must not remove #file tags or line numbers            // are corrupted. File tags are removed by the tokenizer.        }        else if (!match ||                 line.find("#if") == 0 ||                 line.find("#else") == 0 ||                 line.find("#elif") == 0 ||                 line.find("#endif") == 0)            line = "";        ret << line << "\n";    }    return expandMacros(ret.str());}std::string Preprocessor::getHeaderFileName(const std::string &str){    std::string result;    std::string::size_type i = str.find("\"");    if (i == std::string::npos)        return result;    for (i = i + 1; i < str.length(); ++i)    {        if (str[i] == '"')            break;        result.append(1, str[i]);    }    return result;}void Preprocessor::handleIncludes(std::string &code, const std::string &filename, const std::list<std::string> &includePaths){//    std::string line;    std::string path = filename;    path.erase(1 + path.find_last_of("\\/"));    std::string::size_type pos = 0;    std::map<std::string, bool> handledFiles;    while ((pos = code.find("#include", pos)) != std::string::npos)    {        // Accept only includes that are at the start of a line        if (pos > 0 && code[pos-1] != '\n')        {            pos += 8; // length of "#include"            continue;        }        std::string::size_type end = code.find("\n", pos);        std::string filename = code.substr(pos, end - pos);        // Remove #include clause        code.erase(pos, end - pos);        filename = getHeaderFileName(filename);        if (filename.length() == 0)            continue;        std::string tempFile = filename;        std::transform(tempFile.begin(), tempFile.end(), tempFile.begin(), static_cast < int(*)(int) > (std::tolower));        if (handledFiles.find(tempFile) != handledFiles.end())        {            // We have processed this file already once, skip            // it this time to avoid ethernal loop.            continue;        }        handledFiles[ tempFile ] = true;        // filename contains now a file name e.g. "menu.h"        std::string processedFile;        for (std::list<std::string>::const_iterator iter = includePaths.begin(); iter != includePaths.end(); ++iter)        {            std::ifstream fin;            fin.open((*iter + filename).c_str());            if (fin.is_open())            {                filename = *iter + filename;                processedFile = Preprocessor::read(fin);                break;            }        }        if (processedFile.length() == 0)        {            filename = path + filename;            std::ifstream fin(filename.c_str());            processedFile = Preprocessor::read(fin);        }        if (processedFile.length() > 0)        {            // Replace all tabs with spaces..            std::replace(processedFile.begin(), processedFile.end(), '\t', ' ');            // Remove all indentation..            if (!processedFile.empty() && processedFile[0] == ' ')                processedFile.erase(0, processedFile.find_first_not_of(" "));            // Remove space characters that are after or before new line character            processedFile = removeSpaceNearNL(processedFile);            processedFile = "#file \"" + filename + "\"\n" + processedFile + "\n#endfile";            code.insert(pos, processedFile);        }    }}class Macro{private:    Tokenizer tokenizer;    std::vector<std::string> _params;    std::string _name;    std::string _macro;    bool _variadic;public:    Macro(const std::string &macro)            : _macro(macro)    {        // Tokenize the macro to make it easier to handle        std::istringstream istr(macro.c_str());        tokenizer.tokenize(istr, "");        // macro name..        if (tokens() && tokens()->isName())            _name = tokens()->str();        _variadic = false;        std::string::size_type pos = macro.find_first_of(" (");        if (pos != std::string::npos && macro[pos] == '(')        {            // Extract macro parameters            if (Token::Match(tokens(), "%var% ( %var%"))            {                for (const Token *tok = tokens()->tokAt(2); tok; tok = tok->next())                {                    if (tok->str() == ")")                        break;                    if (Token::Match(tok, ". . . )"))                    {                        _variadic = true;                        break;                    }                    if (tok->isName())                        _params.push_back(tok->str());                }            }        }    }    const Token *tokens() const    {        return tokenizer.tokens();    }    const std::vector<std::string> params() const    {        return _params;    }    bool variadic() const    {        return _variadic;    }    const std::string &name() const    {        return _name;    }    const std::string code(const std::vector<std::string> &params2) const    {        std::string macrocode;        if (_params.empty())        {            std::string::size_type pos = _macro.find(" ");            if (pos == std::string::npos)                macrocode = "";            else            {                macrocode = _macro.substr(pos + 1);                if ((pos = macrocode.find_first_of("\r\n")) != std::string::npos)                    macrocode.erase(pos);            }        }        else        {            const Token *tok = tokens();            while (tok && tok->str() != ")")                tok = tok->next();            if (tok)            {                bool optcomma = false;                while ((tok = tok->next()) != NULL)                {                    std::string str = tok->str();                    if (str == "##")                        continue;                    if (str[0] == '#' || tok->isName())                    {                        bool stringify = false;                        if (str[0] == '#')                        {                            str = str.erase(0, 1);                            stringify = true;                        }                        for (unsigned int i = 0; i < _params.size(); ++i)                        {                            if (str == _params[i])                            {                                if (_variadic && i == _params.size() - 1)                                {                                    str = "";                                    for (unsigned int j = _params.size() - 1; j < params2.size(); ++j)                                    {                                        if (optcomma || j > _params.size() - 1)                                            str += ",";                                        optcomma = false;                                        str += params2[j];                                    }                                    break;                                }                                if (stringify)                                    str = "\"" + params2[i] + "\"";                                else                                    str = params2[i];                                break;                            }                        }                    }                    if (_variadic && Token::Match(tok, ",") && tok->next() && Token::Match(tok->next(), "##"))                    {                        optcomma = true;                        continue;                    }                    optcomma = false;                    macrocode += str;                    if (Token::Match(tok, "%type% %var%"))                        macrocode += " ";                }            }        }        return macrocode;    }};std::string Preprocessor::expandMacros(std::string code){    // Search for macros and expand them..    std::string::size_type defpos = 0;    while ((defpos = code.find("#define ", defpos)) != std::string::npos)    {        if (defpos > 0 && code[defpos-1] != '\n')        {            defpos += 6;            continue;        }        // Get macro..        std::string::size_type endpos = code.find("\n", defpos + 6);        if (endpos == std::string::npos)        {            code.erase(defpos);            break;        }        // Extract the whole macro into a separate variable "macro" and then erase it from "code"        const Macro macro(code.substr(defpos + 8, endpos - defpos - 7));        code.erase(defpos, endpos - defpos);        // No macro name => continue        if (macro.name() == "")            continue;        // Expand all macros in the code..        char pattern[5] = "\"'# ";        pattern[3] = macro.name().at(0);        std::string::size_type pos1 = defpos;        while ((pos1 = code.find_first_of(pattern, pos1 + 1)) != std::string::npos)        {            char ch = code[pos1];            // #undef => break            if (code[pos1] == '#')            {                // Are we at a #undef or #define?                if (code.substr(pos1, 7) == "#undef ")                    pos1 += 7;                else if (code.substr(pos1, 8) == "#define ")                    pos1 += 8;                else                    continue;                // Compare the macroname with the macroname we're currently parsing (macro.name())                // If it's the same macroname.. break.                std::string::size_type pos = pos1 + macro.name().length();                if (pos < code.length()                    && code.substr(pos1, macro.name().length()) == macro.name()                    && !std::isalnum(code[pos]) && code[pos] != '_')                    break;                continue;            }            // String or char..            if (code[pos1] == '\"' || code[pos1] == '\'')            {                //char ch = code[pos1];                ++pos1;                while (code[pos1] != ch)                {                    if (code[pos1] == '\\')                        ++pos1;                    ++pos1;                    if (!code[pos1])                    {                        // This should not happen, if it does, there is a bug in cppcheck.                        std::cout << "\n\n####### There is a bug in preprocessor.cpp that can cause crash, shutting down.\n\n" << std::endl;                        std::exit(0);                    }                }                continue;            }            // Matching the macroname?            const std::string substr(code.substr(pos1, macro.name().length()));            if (code.substr(pos1, macro.name().length()) != macro.name())                continue;            // Previous char must not be alphanumeric or '_'            if (pos1 != 0 && (std::isalnum(code[pos1-1]) || code[pos1-1] == '_'))                continue;            // The char after the macroname must not be alphanumeric or '_'            if (pos1 + macro.name().length() < code.length())            {                std::string::size_type pos2 = pos1 + macro.name().length();                if (std::isalnum(code[pos2]) || code[pos2] == '_')                    continue;            }            std::vector<std::string> params;            std::string::size_type pos2 = pos1 + macro.name().length();            if (macro.params().size() && pos2 >= code.length())                continue;            if (macro.params().size())            {                if (code[pos2] != '(')                    continue;                int parlevel = 0;                std::string par;                for (; pos2 < code.length(); ++pos2)                {                    if (code[pos2] == '(')                    {                        ++parlevel;                        if (parlevel == 1)                            continue;                    }                    else if (code[pos2] == ')')                    {                        --parlevel;                        if (parlevel <= 0)                        {                            params.push_back(par);                            break;                        }                    }                    else if (code[pos2] == '\"' || code[pos2] == '\'')                    {                        par += code[pos2];                        char ch = code[pos2];                        ++pos2;                        while (pos2 < code.length() && code[pos2] != ch)                        {                            par += code[pos2];                            if (code[pos2] == '\\')                            {                                par += code[pos2];                                ++pos2;                            }                            ++pos2;                        }                        if (pos2 == code.length())                            break;                        par += code[pos2];                        continue;                    }                    if (parlevel == 1 && code[pos2] == ',')                    {                        params.push_back(par);                        par = "";                    }                    else if (parlevel >= 1)                    {                        par += std::string(1, code[pos2]);                    }                }            }            // Same number of parameters..            if (!macro.variadic() && params.size() != macro.params().size())                continue;            // Create macro code..            const std::string macrocode(macro.code(params));            // Insert macro code..            if (!macro.params().empty())                ++pos2;            code.erase(pos1, pos2 - pos1);            code.insert(pos1, macrocode);            pos1 += macrocode.length() - 1;        }    }    // Remove all #undef..    defpos = 0;    while ((defpos = code.find("\n#undef ", defpos)) != std::string::npos)    {        ++defpos;        std::string::size_type pos2 = code.find("\n", defpos);        code.erase(defpos, pos2 - defpos);    }    return code;}

⌨️ 快捷键说明

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