diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/log.cc | 255 | ||||
-rw-r--r-- | common/log.h | 96 |
2 files changed, 351 insertions, 0 deletions
diff --git a/common/log.cc b/common/log.cc new file mode 100644 index 00000000..86379186 --- /dev/null +++ b/common/log.cc @@ -0,0 +1,255 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * 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 <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <vector> +#include <list> +#include <map> +#include <set> + +#include "log.h" +#include "design.h" + +std::vector<FILE*> log_files; +std::vector<std::ostream*> log_streams; +std::map<std::string, std::set<std::string>> log_hdump; +bool log_hdump_all = false; +FILE *log_errfile = NULL; + +bool log_error_stderr = false; +bool log_cmd_error_throw = false; +bool log_quiet_warnings = false; +int log_verbose_level; +std::string log_last_error; +void (*log_error_atexit)() = NULL; + +static bool next_print_log = false; +static int log_newline_count = 0; + +std::string vstringf(const char *fmt, va_list ap) +{ + std::string string; + char *str = NULL; + +#ifdef _WIN32 + int sz = 64+strlen(fmt), rc; + while (1) { + va_list apc; + va_copy(apc, ap); + str = (char*)realloc(str, sz); + rc = vsnprintf(str, sz, fmt, apc); + va_end(apc); + if (rc >= 0 && rc < sz) + break; + sz *= 2; + } +#else + if (vasprintf(&str, fmt, ap) < 0) + str = NULL; +#endif + + if (str != NULL) { + string = str; + free(str); + } + + return string; +} + +void logv(const char *format, va_list ap) +{ + // + // Trim newlines from the beginning + while (format[0] == '\n' && format[1] != 0) { + log("\n"); + format++; + } + + std::string str = vstringf(format, ap); + + if (str.empty()) + return; + + size_t nnl_pos = str.find_last_not_of('\n'); + if (nnl_pos == std::string::npos) + log_newline_count += str.size(); + else + log_newline_count = str.size() - nnl_pos - 1; + + for (auto f : log_files) + fputs(str.c_str(), f); + + for (auto f : log_streams) + *f << str; +} + +void logv_header(const char *format, va_list ap) +{ +/* + log_spacer(); + + std::string header_id; + + log("%s. ", header_id.c_str()); + logv(format, ap); + log_flush(); +*/ +} + +void logv_warning(const char *format, va_list ap) +{ + std::string message = vstringf(format, ap); + + log("Warning: %s", message.c_str()); + log_flush(); +} + +void logv_warning_noprefix(const char *format, va_list ap) +{ + std::string message = vstringf(format, ap); + + log("%s", message.c_str()); +} + +void logv_error(const char *format, va_list ap) +{ +#ifdef EMSCRIPTEN + auto backup_log_files = log_files; +#endif + + if (log_errfile != NULL) + log_files.push_back(log_errfile); + + if (log_error_stderr) + for (auto &f : log_files) + if (f == stdout) + f = stderr; + + log_last_error = vstringf(format, ap); + log("ERROR: %s", log_last_error.c_str()); + log_flush(); + + if (log_error_atexit) + log_error_atexit(); + +#ifdef EMSCRIPTEN + log_files = backup_log_files; + throw 0; +#elif defined(_MSC_VER) + _exit(1); +#else + _Exit(1); +#endif +} + +void log(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + logv(format, ap); + va_end(ap); +} + +void log_header(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + logv_header(format, ap); + va_end(ap); +} + +void log_warning(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + logv_warning(format, ap); + va_end(ap); +} + +void log_warning_noprefix(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + logv_warning_noprefix(format, ap); + va_end(ap); +} + +void log_error(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + logv_error(format, ap); +} + +void log_cmd_error(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + + if (log_cmd_error_throw) { + log_last_error = vstringf(format, ap); + log("ERROR: %s", log_last_error.c_str()); + log_flush(); + throw log_cmd_error_exception(); + } + + logv_error(format, ap); +} + +void log_spacer() +{ + if (log_newline_count < 2) log("\n"); + if (log_newline_count < 2) log("\n"); +} + +void log_push() +{ +} + +void log_pop() +{ + log_flush(); +} + +void log_reset_stack() +{ + log_flush(); +} + +void log_flush() +{ + for (auto f : log_files) + fflush(f); + + for (auto f : log_streams) + f->flush(); +} + +void log_cell(CellInfo *cell, std::string indent) +{ +} + +void log_net(NetInfo *net, std::string indent) +{ +} + + diff --git a/common/log.h b/common/log.h new file mode 100644 index 00000000..c2a4ab0f --- /dev/null +++ b/common/log.h @@ -0,0 +1,96 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * 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. + * + */ + +#ifndef LOG_H +#define LOG_H + +#include <ostream> +#include <string> +#include <vector> +#include <set> +#include <stdio.h> +#include <stdarg.h> + +#include "design.h" + +// from libs/sha1/sha1.h + +#define NXP_NORETURN +#define NXP_ATTRIBUTE(...) __attribute__((__VA_ARGS__)) + +struct log_cmd_error_exception { }; + +extern std::vector<FILE*> log_files; +extern std::vector<std::ostream*> log_streams; +extern std::set<std::string> log_warnings; +extern int log_warnings_count; +extern bool log_hdump_all; +extern FILE *log_errfile; + +extern bool log_quiet_warnings; +extern int log_verbose_level; +extern std::string log_last_error; +extern void (*log_error_atexit)(); + +void logv(const char *format, va_list ap); +void logv_warning(const char *format, va_list ap); +void logv_warning_noprefix(const char *format, va_list ap); +NXP_NORETURN void logv_error(const char *format, va_list ap) + NXP_ATTRIBUTE(noreturn); + +void log(const char *format, ...); +void log_header(const char *format, ...); +void log_warning(const char *format, ...); +void log_warning_noprefix(const char *format, ...); +NXP_NORETURN void log_error(const char *format, ...); +NXP_NORETURN void log_cmd_error(const char *format, ...); + +void log_spacer(); +void log_push(); +void log_pop(); + +void log_backtrace(const char *prefix, int levels); +void log_reset_stack(); +void log_flush(); + +/* +const char *log_id(RTLIL::IdString id); + +template<typename T> static inline const char *log_id(T *obj) { + return log_id(obj->name); +} +*/ + +void log_cell(CellInfo *cell, std::string indent = ""); +void log_net(NetInfo *net, std::string indent = ""); + +#ifndef NDEBUG +static inline void log_assert_worker(bool cond, const char *expr, const char *file, int line) { + if (!cond) log_error("Assert `%s' failed in %s:%d.\n", expr, file, line); +} +# define log_assert(_assert_expr_) YOSYS_NAMESPACE_PREFIX log_assert_worker(_assert_expr_, #_assert_expr_, __FILE__, __LINE__) +#else +# define log_assert(_assert_expr_) +#endif + +#define log_abort() log_error("Abort in %s:%d.\n", __FILE__, __LINE__) +#define log_ping() log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__) + + +#endif |