Files
ldc/gen/configfile.cpp
David Nadlinger 7eda270d6b Search for config next to the binary before trying global dirs.
This solves the problem of LDC picking up a pre-existing system-wide config when druntime and Phobos are compiled as part of the build process.

This order was intended by Christian in 919f8d6, but then backed out again in eb3cd887 with no comment as to why – I hope this doesn't have any unwanted implications.
2011-11-12 14:35:30 +01:00

175 lines
4.1 KiB
C++

#include <iostream>
#include <string>
#include <cassert>
#include <cstring>
#include "llvm/Support/Path.h"
#include "libconfig.h++"
#include "gen/configfile.h"
#include "mars.h"
namespace sys = llvm::sys;
ConfigFile::ConfigFile()
{
cfg = new libconfig::Config;
}
ConfigFile::~ConfigFile()
{
delete cfg;
}
bool ConfigFile::locate(sys::Path& p, const char* argv0, void* mainAddr, const char* filename)
{
// temporary configuration
// try the current working dir
p = sys::Path::GetCurrentDirectory();
p.appendComponent(filename);
if (p.exists())
return true;
// try next to the executable
p = sys::Path::GetMainExecutable(argv0, mainAddr);
p.eraseComponent();
p.appendComponent(filename);
if (p.exists())
return true;
// user configuration
// try ~/.ldc
p = sys::Path::GetUserHomeDirectory();
p.appendComponent(".ldc");
p.appendComponent(filename);
if (p.exists())
return true;
#if _WIN32
// try home dir
p = sys::Path::GetUserHomeDirectory();
p.appendComponent(filename);
if (p.exists())
return true;
#endif
// system configuration
#if _WIN32
// try the install-prefix
p = sys::Path(LDC_INSTALL_PREFIX);
p.appendComponent(filename);
if (p.exists())
return true;
#else
// try the install-prefix/etc
p = sys::Path(LDC_INSTALL_PREFIX);
p.appendComponent("etc");
p.appendComponent(filename);
if (p.exists())
return true;
// try the install-prefix/etc/ldc
p = sys::Path(LDC_INSTALL_PREFIX);
p.appendComponent("etc");
p.appendComponent("ldc");
p.appendComponent(filename);
if (p.exists())
return true;
// try /etc (absolute path)
p = sys::Path("/etc");
p.appendComponent(filename);
if (p.exists())
return true;
// try /etc/ldc (absolute path)
p = sys::Path("/etc/ldc");
p.appendComponent(filename);
if (p.exists())
return true;
#endif
return false;
}
bool ConfigFile::read(const char* argv0, void* mainAddr, const char* filename)
{
sys::Path p;
if (!locate(p, argv0, mainAddr, filename))
{
// failed to find cfg, users still have the DFLAGS environment var
std::cerr << "Error failed to locate the configuration file: " << filename << std::endl;
return false;
}
// save config file path for -v output
pathstr = p.str();
try
{
// read the cfg
cfg->readFile(p.c_str());
// make sure there's a default group
if (!cfg->exists("default"))
{
std::cerr << "no default settings in configuration file" << std::endl;
return false;
}
libconfig::Setting& root = cfg->lookup("default");
if (!root.isGroup())
{
std::cerr << "default is not a group" << std::endl;
return false;
}
// handle switches
if (root.exists("switches"))
{
std::string binpathkey = "%%ldcbinarypath%%";
std::string binpath = sys::Path::GetMainExecutable(argv0, mainAddr).getDirname();
libconfig::Setting& arr = cfg->lookup("default.switches");
int len = arr.getLength();
for (int i=0; i<len; i++)
{
std::string v = arr[i];
// replace binpathkey with binpath
size_t p;
while (std::string::npos != (p = v.find(binpathkey)))
v.replace(p, binpathkey.size(), binpath);
switches.push_back(strdup(v.c_str()));
}
}
}
catch(libconfig::FileIOException& fioe)
{
std::cerr << "Error reading configuration file: " << filename << std::endl;
return false;
}
catch(libconfig::ParseException& pe)
{
std::cerr << "Error parsing configuration file: " << filename
<< "(" << pe.getLine() << "): " << pe.getError() << std::endl;
return false;
}
catch(...)
{
std::cerr << "Unknown exception caught!" << std::endl;
return false;
}
return true;
}