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"));
}
|