blob: 4063802bbb543cfbab83b78d84480567a99bb269 [file] [log] [blame]
#ifndef LIBTRELLIS_DATABASEPATH_H
#define LIBTRELLIS_DATABASEPATH_H
#include <boost/version.hpp>
#include <boost/filesystem.hpp>
#if BOOST_VERSION >= 106100
#include <boost/dll/runtime_symbol_info.hpp>
std::string get_database_path()
{
boost::filesystem::path executable_path = boost::dll::program_location().parent_path();
boost::filesystem::path database_datadir_relative(TRELLIS_RPATH_DATADIR "/trellis/database");
std::string database_folder = (executable_path /= database_datadir_relative).string();
return database_folder;
}
#else
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include <errno.h>
#include <string>
#include <sstream>
#include <cstring>
#ifdef _WIN32
# include <windows.h>
# include <io.h>
#elif defined(__APPLE__)
# include <mach-o/dyld.h>
# include <unistd.h>
#else
# include <unistd.h>
#endif
#ifdef __FreeBSD__
# include <sys/sysctl.h>
#endif
#include <limits.h>
#if defined(__linux__) || defined(__CYGWIN__)
std::string proc_self_dirname()
{
char path[PATH_MAX];
ssize_t buflen = readlink("/proc/self/exe", path, sizeof(path));
if (buflen < 0) {
fprintf(stderr, "fatal error: readlink(\"/proc/self/exe\") failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
while (buflen > 0 && path[buflen-1] != '/')
buflen--;
return std::string(path, buflen);
}
#elif defined(__FreeBSD__)
std::string proc_self_dirname()
{
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
size_t buflen;
char *buffer;
std::string path;
if (sysctl(mib, 4, NULL, &buflen, NULL, 0) != 0) {
fprintf(stderr, "fatal error: sysctl failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
buffer = (char*)malloc(buflen);
if (buffer == NULL) {
fprintf(stderr, "fatal error: malloc failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (sysctl(mib, 4, buffer, &buflen, NULL, 0) != 0) {
fprintf(stderr, "fatal error: sysctl failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
while (buflen > 0 && buffer[buflen-1] != '/')
buflen--;
path.assign(buffer, buflen);
free(buffer);
return path;
}
#elif defined(__APPLE__)
std::string proc_self_dirname()
{
char *path = NULL;
uint32_t buflen = 0;
while (_NSGetExecutablePath(path, &buflen) != 0)
path = (char *) realloc((void *) path, buflen);
while (buflen > 0 && path[buflen-1] != '/')
buflen--;
return std::string(path, buflen);
}
#elif defined(_WIN32)
std::string proc_self_dirname()
{
int i = 0;
# ifdef __MINGW32__
char longpath[MAX_PATH + 1];
char shortpath[MAX_PATH + 1];
# else
WCHAR longpath[MAX_PATH + 1];
TCHAR shortpath[MAX_PATH + 1];
# endif
if (!GetModuleFileName(0, longpath, MAX_PATH+1)) {
fprintf(stderr, "fatal error: GetModuleFileName() failed.\n");
exit(EXIT_FAILURE);
}
if (!GetShortPathName(longpath, shortpath, MAX_PATH+1)) {
fprintf(stderr, "fatal error: GetShortPathName() failed.\n");
exit(EXIT_FAILURE);
}
while (shortpath[i] != 0)
i++;
while (i > 0 && shortpath[i-1] != '/' && shortpath[i-1] != '\\')
shortpath[--i] = 0;
std::string path;
for (i = 0; shortpath[i]; i++)
path += char(shortpath[i]);
return path;
}
#elif defined(EMSCRIPTEN)
std::string proc_self_dirname()
{
return "/";
}
#else
#error Dont know how to determine process executable base path!
#endif
std::string get_database_path()
{
boost::filesystem::path executable_path = boost::filesystem::path(proc_self_dirname()).parent_path();
boost::filesystem::path database_datadir_relative(TRELLIS_RPATH_DATADIR "/trellis/database");
std::string database_folder = (executable_path /= database_datadir_relative).string();
return database_folder;
}
#endif
#endif //LIBTRELLIS_DATABASEPATH_HPP