File: configfile.d

package info (click to toggle)
ldc 1%3A1.30.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 59,248 kB
  • sloc: cpp: 61,598; ansic: 14,545; sh: 1,014; makefile: 972; asm: 510; objc: 135; exp: 48; python: 12
file content (188 lines) | stat: -rw-r--r-- 5,561 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//===-- driver/configfile.d - LDC config file handling ------------*- D -*-===//
//
//                         LDC – the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// Handles reading and parsing of an LDC config file (ldc.conf/ldc2.conf).
//
//===----------------------------------------------------------------------===//
module driver.configfile;

import dmd.root.array;
import driver.config;
import core.stdc.stdio;
import core.stdc.string;


string prepareBinDir(const(char)* binDir)
{
    immutable len = strlen(binDir);
    auto res = binDir[0 .. len].dup;
    foreach (ref c; res)
    {
        if (c == '\\') c = '/';
    }
    return cast(string)res; // assumeUnique
}

T findSetting(T)(GroupSetting[] sections, Setting.Type type, string name)
{
    // lexically later sections dominate earlier ones
    foreach_reverse (section; sections)
    {
        foreach (c; section.children)
        {
            if (c.type == type && c.name == name)
                return cast(T) c;
        }
    }
    return null;
}

ArraySetting findArraySetting(GroupSetting[] sections, string name)
{
    return findSetting!ArraySetting(sections, Setting.Type.array, name);
}

ScalarSetting findScalarSetting(GroupSetting[] sections, string name)
{
    return findSetting!ScalarSetting(sections, Setting.Type.scalar, name);
}

string replace(string str, string pattern, string replacement)
{
    string res;
    size_t cap = str.length;
    if (replacement.length > pattern.length)
        cap += replacement.length - pattern.length;
    reserve(res, cap);

    while (str.length)
    {
        if (str.length < pattern.length)
        {
            res ~= str;
            str = null;
        }
        else if (str[0 .. pattern.length] == pattern)
        {
            res ~= replacement;
            str = str[pattern.length .. $];
        }
        else
        {
            res ~= str[0];
            str = str[1 .. $];
        }
    }
    return res;
}

unittest
{
    enum pattern = "pattern";
    enum test1 = "find the pattern in a sentence";
    enum test2 = "find the pattern";
    enum test3 = "pattern in a sentence";
    enum test4 = "a pattern, yet other patterns";

    assert(replace(test1, pattern, "word") == "find the word in a sentence");
    assert(replace(test2, pattern, "word") == "find the word");
    assert(replace(test3, pattern, "word") == "word in a sentence");
    assert(replace(test4, pattern, "word") == "a word, yet other words");
}


extern(C++) struct ConfigFile
{
    __gshared ConfigFile instance;

private:

    // representation

    const(char)* pathcstr;
    Array!(const(char)*) switches;
    Array!(const(char)*) postSwitches;
    Array!(const(char)*) _libDirs;
    const(char)* rpathcstr;

    static bool sectionMatches(const(char)* section, const(char)* triple);

    bool readConfig(const(char)* cfPath, const(char)* triple, const(char)* binDir)
    {
        switches.setDim(0);
        postSwitches.setDim(0);

        immutable dBinDir = prepareBinDir(binDir);

        try
        {
            GroupSetting[] sections; // in lexical order
            foreach (s; parseConfigFile(cfPath))
            {
                if (s.type == Setting.Type.group &&
                    (s.name == "default" || sectionMatches((s.name ~ '\0').ptr, triple)))
                {
                    sections ~= cast(GroupSetting) s;
                }
            }

            if (sections.length == 0)
            {
                const dTriple = triple[0 .. strlen(triple)];
                const dCfPath = cfPath[0 .. strlen(cfPath)];
                throw new Exception("No matching section for triple '" ~ cast(string) dTriple
                                    ~ "' in " ~ cast(string) dCfPath);
            }

            auto switches = findArraySetting(sections, "switches");
            auto postSwitches = findArraySetting(sections, "post-switches");
            if (!switches && !postSwitches)
            {
                const dCfPath = cfPath[0 .. strlen(cfPath)];
                throw new Exception("Could not look up switches in " ~ cast(string) dCfPath);
            }

            void applyArray(ref Array!(const(char)*) output, ArraySetting input)
            {
                if (!input)
                    return;

                output.reserve(input.vals.length);
                foreach (sw; input.vals)
                {
                    const finalSwitch = sw.replace("%%ldcbinarypath%%", dBinDir) ~ '\0';
                    output.push(finalSwitch.ptr);
                }
            }

            applyArray(this.switches, switches);
            applyArray(this.postSwitches, postSwitches);

            auto libDirs = findArraySetting(sections, "lib-dirs");
            applyArray(_libDirs, libDirs);

            if (auto rpath = findScalarSetting(sections, "rpath"))
                this.rpathcstr = (rpath.val.replace("%%ldcbinarypath%%", dBinDir) ~ '\0').ptr;

            return true;
        }
        catch (Exception ex)
        {
            fprintf(stderr, "Error: %.*s\n", cast(int) ex.msg.length, ex.msg.ptr);
            return false;
        }
    }
}

unittest
{
    assert(ConfigFile.sectionMatches("i[3-6]86-.*-windows-msvc", "i686-pc-windows-msvc"));
    assert(ConfigFile.sectionMatches("86(_64)?-.*-linux", "x86_64--linux-gnu"));
    assert(!ConfigFile.sectionMatches("^linux", "x86_64--linux-gnu"));
}