diff --git a/include/rosa/config/config.h b/include/rosa/config/config.h index 0359759..9cdc02a 100644 --- a/include/rosa/config/config.h +++ b/include/rosa/config/config.h @@ -1,51 +1,55 @@ /******************************************************************************* * * File: config.h * * Contents: Configuration nformation on the build of the library. * * Copyright 2017 * * Author: David Juhasz (david.juhasz@tuwien.ac.at) * ******************************************************************************/ #ifndef ROSA_CONFIG_CONFIG_H #define ROSA_CONFIG_CONFIG_H #include // Various preprocessor macros containing config information. #include "rosa/config/rosa-config.h" // This OS-specific block defines one of the following: // - ROSA_LINUX // - ROSA_WINDOWS // It also defines ROSA_POSIX for POSIX-compatible systems #if defined(__linux__) #define ROSA_LINUX #elif defined(WIN32) || defined(_WIN32) #define ROSA_WINDOWS #else #error Platform and/or compiler not supported #endif #if defined(ROSA_LINUX) #define ROSA_POSIX #endif +// Defining filenames in a project-relative way based on absolute paths. +#include "rosa/config/project_path.hpp" +#define __FILENAME__ (__FILE__ + project_relative_path_index(__FILE__)) + // Convenience macros. #define ROSA_VOID_STMT static_cast(0) #define ROSA_IGNORE_UNUSED(x) static_cast(x) #define ROSA_CRITICAL(error) \ do { \ - std::cerr << "[FATAL] " << __FILE__ << ":" << __LINE__ \ + std::cerr << "[FATAL] " << __FILENAME__ << ":" << __LINE__ \ << ": critical error: '" << (error) << "'" << std::endl; \ ::abort(); \ } while (false) #define ROSA_RAISE_ERROR(msg) throw std::runtime_error(msg) #endif // ROSA_CONFIG_CONFIG_H diff --git a/include/rosa/config/project_path.hpp b/include/rosa/config/project_path.hpp new file mode 100644 index 0000000..1dac229 --- /dev/null +++ b/include/rosa/config/project_path.hpp @@ -0,0 +1,50 @@ +/******************************************************************************* + * + * File: project_path.hpp + * + * Contents: Facility for compile-time manipulation of paths. + * + * Copyright 2017 + * + * Author: David Juhasz (david.juhasz@tuwien.ac.at) + * + ******************************************************************************/ + +#ifndef ROSA_SUPPORT_PROJECT_PATH_H +#define ROSA_SUPPORT_PROJECT_PATH_H + +#include "rosa/config/rosa-config.h" + +namespace rosa { + +// Nested namespace containing the implementation of the provided features, +// not supposed to be used directly. +namespace impl { + +// Implementation of the static search for the project-relative part of an +// absolute path. +constexpr size_t +project_relative_path_index_impl(const char *const path, + const char *const project = ROSA_SRC_DIR, + const size_t index = 0) { + return project[index] == '\0' + ? index // Found it. + : (path[index] == '\0' || project[index] != path[index]) + ? 0 // Path is not under project. + : project_relative_path_index_impl( + path, project, + index + 1); // Continue searching... +} + +} // End namespace impl + +// Staticaly finds the index of the project-relative part of a absolute path. +// Returns 0 if the absolute path is not located under the project directory. +constexpr size_t project_relative_path_index(const char * const path) { + return impl::project_relative_path_index_impl(path); +} + +} // End namespace rosa + +#endif // ROSA_SUPPORT_PROJECT_PATH_H + diff --git a/include/rosa/config/rosa-config.h.cmake b/include/rosa/config/rosa-config.h.cmake index 828cb9e..bee01fb 100644 --- a/include/rosa/config/rosa-config.h.cmake +++ b/include/rosa/config/rosa-config.h.cmake @@ -1,42 +1,44 @@ #ifndef ROSA_CONFIG_ROSA_CONFIG_H #define ROSA_CONFIG_ROSA_CONFIG_H #define CMAKE_SYSTEM "${CMAKE_SYSTEM}" #define CMAKE_GENERATOR "${CMAKE_GENERATOR}" #define CMAKE_C_COMPILER_ID "${CMAKE_C_COMPILER_ID}" #define CMAKE_C_COMPILER_VERSION "${CMAKE_C_COMPILER_VERSION}" #define CMAKE_CXX_COMPILER_ID "${CMAKE_CXX_COMPILER_ID}" #define CMAKE_CXX_COMPILER_VERSION "${CMAKE_CXX_COMPILER_VERSION}" #define ROSA_VERSION_MAJOR ${ROSA_VERSION_MAJOR} #define ROSA_VERSION_MINOR ${ROSA_VERSION_MINOR} #define ROSA_VERSION_PATCH ${ROSA_VERSION_PATCH} #define PACKAGE_NAME "${PACKAGE_NAME}" #define PACKAGE_STRING "${PACKAGE_STRING}" #define PACKAGE_VERSION "${PACKAGE_VERSION}" #define PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}" #define BUILD_DATE __DATE__ " " __TIME__ +#define ROSA_SRC_DIR "${ROSA_MAIN_SRC_DIR}" + #if ${ROSA_LOG_LEVEL_INT} != -1 #define ROSA_LOG_LEVEL ${ROSA_LOG_LEVEL} #endif #if ${ROSA_ENABLE_ASSERTIONS_INT} != -1 #define ROSA_ENABLE_ASSERTIONS #endif #endif // ROSA_CONFIG_ROSA_CONFIG_H diff --git a/include/rosa/support/debug.hpp b/include/rosa/support/debug.hpp index f4d9c2a..47e94de 100644 --- a/include/rosa/support/debug.hpp +++ b/include/rosa/support/debug.hpp @@ -1,82 +1,82 @@ /******************************************************************************* * * File: debug.hpp * * Contents: Facility for debugging * * Copyright 2017 * * Author: David Juhasz (david.juhasz@tuwien.ac.at) * ******************************************************************************/ #ifndef ROSA_SUPPORT_DEBUG_HPP #define ROSA_SUPPORT_DEBUG_HPP #include "rosa/config/config.h" #include "rosa/support/types.hpp" #include #include namespace rosa { // Returns an output stream to use for debugging. std::ostream &dbgs(void); // Prints an array to the ostream. template std::ostream &operator<<(std::ostream &os, const std::array &arr) { os << '['; for (unsigned I = 0; I < size; ++I) { if (I) { os << ','; } os << (PRINTABLE(T)) arr[I]; } os << ']'; return os; } } // End namespace rosa #ifndef ROSA_ENABLE_ASSERTIONS #define ASSERT(stmt) ROSA_IGNORE_UNUSED(stmt) #elif defined(ROSA_WINDOWS) #define ASSERT(stmt) \ if (static_cast(stmt) == false) { \ - rosa::dbgs() << __FILE__ << ":" << __LINE__ << ": requirement failed: '" \ - << #stmt << "'" << std::endl; \ + rosa::dbgs() << __FILENAME__ << ":" << __LINE__ \ + << ": requirement failed: '" << #stmt << "'" << std::endl; \ ::abort(); \ } \ ROSA_VOID_STMT #else // defined(ROSA_LINUX) #include #define ASSERT(stmt) \ if (static_cast(stmt) == false) { \ - rosa::dbgs() << __FILE__ << ":" << __LINE__ << ": requirement failed: '" \ - << #stmt << "'" << std::endl; \ + rosa::dbgs() << __FILENAME__ << ":" << __LINE__ \ + << ": requirement failed: '" << #stmt << "'" << std::endl; \ void *array[20]; \ auto bt_size = ::backtrace(array, 20); \ ::backtrace_symbols_fd(array, bt_size, 2); \ ::abort(); \ } \ ROSA_VOID_STMT #endif // defined(ROSA_ENABLE_ASSERTIONS) #ifndef NDEBUG #define DEBUG(X) \ do { \ X; \ } while (false) #define DEBUGVAR(V) \ do { \ - rosa::dbgs() << #V << " (" << __FILE__ << ":" << __LINE__ << "): " << (V) \ - << std::endl; \ + rosa::dbgs() << #V << " (" << __FILENAME__ << ":" << __LINE__ \ + << "): " << (V) << std::endl; \ } while (false) #else // defined(NDEBUG) #define DEBUG(X) ROSA_IGNORE_UNUSED(X) #define DEBUGVAR(X) ROSA_IGNORE_UNUSED(X) #endif // defined(NDEBUG) #endif // ROSA_SUPPORT_DEBUG_HPP diff --git a/include/rosa/support/log.h b/include/rosa/support/log.h index 0959866..315f096 100644 --- a/include/rosa/support/log.h +++ b/include/rosa/support/log.h @@ -1,97 +1,98 @@ /******************************************************************************* * * File: log.h * * Contents: Facility for logging * * Copyright 2017 * * Author: David Juhasz (david.juhasz@tuwien.ac.at) * ******************************************************************************/ #ifndef ROSA_SUPPORT_LOG_H #define ROSA_SUPPORT_LOG_H #include "debug.hpp" #include // Valid log levels. // NOTE: Keep in sync with the values of enum class rosa::LogLevel. #define ROSA_LOG_LEVEL_ERROR 0 #define ROSA_LOG_LEVEL_WARNING 1 #define ROSA_LOG_LEVEL_INFO 2 #define ROSA_LOG_LEVEL_DEBUG 3 #define ROSA_LOG_LEVEL_TRACE 4 namespace rosa { // Type-safe definition of log levels. // NOTE: Keep values in sync with the corresponding preprocessor definitions. enum class LogLevel { Error = ROSA_LOG_LEVEL_ERROR, Warning = ROSA_LOG_LEVEL_WARNING, Info = ROSA_LOG_LEVEL_INFO, Debug = ROSA_LOG_LEVEL_DEBUG, Trace = ROSA_LOG_LEVEL_TRACE }; // Converts a LogLevel to its string representation. std::string logLevelToString(const LogLevel logLevel); } // End namespace rosa // Simple logging implementation. // FIXME: Make logging thread-safe. #define ROSA_LOG_IMPL(level, output) \ do { \ - rosa::dbgs() << "[" << rosa::logLevelToString(level) << "] " << __FILE__ \ - << ":" << __LINE__ << ": " << (output) << std::endl; \ + rosa::dbgs() << "[" << rosa::logLevelToString(level) << "] " << __func__ \ + << "@" << __FILENAME__ << ":" << __LINE__ << ": " << (output) \ + << std::endl; \ } while (false) // Define logging macros if logging is enabled. #ifdef ROSA_LOG_LEVEL #define LOG_ERROR(output) ROSA_LOG_IMPL(rosa::LogLevel::Error, output) #if ROSA_LOG_LEVEL >= ROSA_LOG_LEVEL_WARNING #define LOG_WARNING(output) ROSA_LOG_IMPL(rosa::LogLevel::Warning, output) #endif #if ROSA_LOG_LEVEL >= ROSA_LOG_LEVEL_INFO #define LOG_INFO(output) ROSA_LOG_IMPL(rosa::LogLevel::Info, output) #endif #if ROSA_LOG_LEVEL >= ROSA_LOG_LEVEL_DEBUG #define LOG_DEBUG(output) ROSA_LOG_IMPL(rosa::LogLevel::Debug, output) #endif #if ROSA_LOG_LEVEL >= ROSA_LOG_LEVEL_TRACE #define LOG_TRACE(output) ROSA_LOG_IMPL(rosa::LogLevel::Trace, output) #endif #endif // defined ROSA_LOG_LEVEL // Define all disabled logging features as void. #ifndef LOG_ERROR #define LOG_ERROR(output) ROSA_IGNORE_UNUSED(output) #endif #ifndef LOG_WARNING #define LOG_WARNING(output) ROSA_IGNORE_UNUSED(output) #endif #ifndef LOG_INFO #define LOG_INFO(output) ROSA_IGNORE_UNUSED(output) #endif #ifndef LOG_DEBUG #define LOG_DEBUG(output) ROSA_IGNORE_UNUSED(output) #endif #ifndef LOG_TRACE #define LOG_TRACE(output) ROSA_IGNORE_UNUSED(output) #endif #endif // ROSA_SUPPORT_LOG_H