Wednesday, February 19, 2020

More tweaks on the tool

The tool now is much more organized than the one in the previous post. This is the new updated code for Preprocess method. The code is much more cleaner, but theres additional functionalities, one of which is that if any files that are included using "" and the tool isn't able to find it. It will output an error message and write a comment that says the file might be an external file that is not part of Gateware.

void File::Preprocess(FileHeap& headerHeap, FileHeap& sourceHeap)
{
    GW::SYSTEM::GFile gFile;
    gFile.Create();
    // iterate through the raw data and read line by line until we found an include
    for (auto iter = std::sregex_iterator(rawData.begin(), rawData.end(), REGEX::PoundInclude); iter != std::sregex_iterator(); ++iter)
    {
        std::smatch match = *iter;
        std::string lineString = match.str(0);
        std::string includeDirectory, includeFileName;
        size_t index = lineString.find_last_of("/");
        // there is a file directory
        if (index != std::string::npos)
        {
#if defined (_WIN32)
            includeDirectory = path + '\\' + lineString.substr(lineString.find_first_of("\"") + 1, index - lineString.find_first_of("\"") - 1);
#elif defined(__APPLE__) || defined(__linux__)
            includeDirectory = path + '/' + lineString.substr(lineString.find_first_of("\"") + 1, index - lineString.find_first_of("\"") - 1);
#endif
            includeFileName = lineString.substr(index + 1, lineString.find_last_of("\"") - index - 1);

            gFile.SetCurrentWorkingDirectory(includeDirectory.data());
            std::string temp; temp.resize(260);
            gFile.GetCurrentWorkingDirectory(const_cast<char*>(temp.data()), 260);
            includeDirectory.clear();
#if defined (_WIN32)
            includeDirectory = temp.substr(0, temp.find_last_of('\\'));
#elif defined(__APPLE__) || defined(__linux__)
            includeDirectory = temp.substr(0, temp.find_last_of('/'));
#endif
        }
        // the file directory is in the same directory as this file
        else
        {
            index = lineString.find_first_of("\"");
            includeDirectory = path;
            includeFileName = lineString.substr(index + 1, lineString.find_last_of("\"") - index - 1);
        }
        // reset the working directory back to this files path
        gFile.SetCurrentWorkingDirectory(path.data());
        std::string ext = GetFileExtension(includeFileName);
        if (ext == "h")
        {
            auto headerFile = headerHeap.Find(includeFileName);
            if (!headerFile)
                includeFiles.push_back(headerHeap.Create(includeDirectory, includeFileName));
            else
                includeFiles.push_back(headerFile);
        }
        else if (ext == "hpp")
        {
            auto sourceFile = sourceHeap.Find(includeFileName);
            if (!sourceFile)
                includeFiles.push_back(sourceHeap.Create(includeDirectory, includeFileName));
            else
                includeFiles.push_back(sourceFile);
        }
    }

    for (size_t i = 0; i < includeFiles.size(); ++i)
    {
        includeFiles[i]->Preprocess(headerHeap, sourceHeap);
    }

    auto RetriveFileName = [](const std::string& fileName) -> std::string
    {
        std::string truncatedName;
        size_t index = fileName.find_last_of("/");
        // there is a file directory, if thats the case, we just want the name of the file and remove the last "
        if (index != std::string::npos)
        {
            truncatedName = fileName.substr(fileName.find_last_of("/") + 1);
            truncatedName.erase(truncatedName.size() - 1);
        }
        else // there is no directory for this file, remove the #include and ""
        {
            truncatedName = fileName.substr(fileName.find_first_of("\"") + 1);
            truncatedName.erase(truncatedName.size() - 1);
        }
        return truncatedName;
    };

    std::string newRawData = rawData; // i need a place holder for rawData is because regex_iter will become invalid if original content were modified
    for (auto iter = std::sregex_iterator(rawData.begin(), rawData.end(), REGEX::PoundInclude); iter != std::sregex_iterator(); ++iter)
    {
        std::smatch match = *iter;
        std::string lineString = match.str(0);
        std::string truncatedString = RetriveFileName(lineString);

        std::regex regex(lineString);
        auto headerFile = headerHeap.Find(truncatedString);
        if (headerFile)
        {
            if (headerFile->isExternalFile)
            {
                std::string substitution = lineString + "\t// This file might be an external library file that is not part of Gateware!";
                newRawData = std::regex_replace(newRawData, regex, substitution);
                continue;
            }
            else
            {
                ++headerFile->dependencyCount;
                std::string substitution = "";
                //std::string substitution = "\b"; // Produce weird characters...idk why
                newRawData = std::regex_replace(newRawData, regex, substitution);
                continue;
            }
        }

        auto sourceFile = sourceHeap.Find(truncatedString);
        if (sourceFile)
            newRawData = std::regex_replace(newRawData, regex, sourceFile->GetRawData());
    }
    rawData = std::move(newRawData);
}

No comments:

Post a Comment