header_rewrite.cpp 3.88 KB
Newer Older
1
//*****************************************************************************
2
// Copyright 2017-2020 Intel Corporation
3 4 5 6 7 8 9 10 11 12 13 14 15
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

#include <sstream>
#include <vector>

#include "header_rewrite.hpp"
#include "util.hpp"

using namespace std;

// This function rewrites all of the
// #include "../../blah"
// into something with a dotless relative path. It seems that clang can't handle the .. stuff
// when the header files are stored in its in-memory filesystem.
// Eigen has a lot of .. in their header files.
const string rewrite_header(const string& s, const string& path)
{
32 33 34
    string line = s;
    // only interested in lines starging with '#include' so 8 chars minimum
    if (line.size() > 8)
35
    {
36 37 38
        // skip whitespace
        size_t pos = line.find_first_not_of(" \t");
        if (pos != string::npos && line[pos] == '#' && pos < line.size() - 7)
39
        {
40 41 42
            string directive = line;
            pos = directive.find_first_not_of(" \t", pos + 1);
            if (pos != string::npos)
43
            {
44 45 46 47 48 49 50 51
                directive = directive.substr(pos);
            }
            pos = directive.find_first_of(" \t", pos + 1);
            directive = directive.substr(0, pos);
            if (directive == "include")
            {
                auto line_offset = line.find_first_of("\"<");
                if (line_offset != string::npos)
52
                {
53 54 55
                    string include = line.substr(line_offset);
                    string contents = include.substr(1, include.size() - 2);
                    if (include[1] == '.')
56
                    {
57
                        if (include[2] == '/')
58
                        {
59 60 61 62 63 64 65 66 67 68 69
                            // include starts with './'
                            // rewrite "./blah.h" to "blah.h"
                            contents = contents.substr(2);
                        }
                        else
                        {
                            // include starts with '../'
                            // count number of '../' in string
                            size_t offset = 0;
                            size_t depth = 0;
                            while (contents.substr(offset, 3) == "../")
70
                            {
71 72
                                depth++;
                                offset += 3;
73
                            }
74 75 76 77 78 79
                            string trimmed = contents.substr(offset);
                            vector<string> parts = split(path, '/');
                            parts.pop_back();
                            size_t result_depth = parts.size() - depth;
                            string added_path;
                            for (size_t i = 0; i < result_depth; i++)
80
                            {
81
                                added_path += parts[i] + "/";
82
                            }
83 84 85 86 87 88 89 90 91
                            contents = added_path + trimmed;
                        }
                        if (include[0] == '<')
                        {
                            line = "#include <" + contents + ">";
                        }
                        else
                        {
                            line = "#include \"" + contents + "\"";
92 93 94 95 96 97
                        }
                    }
                }
            }
        }
    }
98
    return line + "\n";
99
}