15f0899efb
Motivation: clang++ on OSX does not support 'thread_local'. Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
110 lines
2.9 KiB
C++
110 lines
2.9 KiB
C++
/*
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
Author: Leonardo de Moura
|
|
*/
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <cstdlib>
|
|
#include "util/thread.h"
|
|
#include "util/debug.h"
|
|
#include "util/script_exception.h"
|
|
|
|
namespace lean {
|
|
script_exception::script_exception(char const * lua_error) {
|
|
lean_assert(lua_error);
|
|
std::string fname;
|
|
std::string line;
|
|
std::string msg;
|
|
int state = 0;
|
|
char const * it = lua_error;
|
|
while (*it) {
|
|
if (state == 0) {
|
|
if (*it == ':') {
|
|
state = 1;
|
|
} else {
|
|
fname += *it;
|
|
}
|
|
} else if (state == 1) {
|
|
if (*it == ':') {
|
|
state = 2;
|
|
} else {
|
|
line += *it;
|
|
}
|
|
} else {
|
|
msg += *it;
|
|
}
|
|
it++;
|
|
}
|
|
if (state != 2) {
|
|
// failed to decode Lua error message
|
|
m_source = source::Unknown;
|
|
m_msg = lua_error;
|
|
} else {
|
|
if (fname == "[string \"...\"]") {
|
|
m_source = source::String;
|
|
} else {
|
|
m_source = source::File;
|
|
m_file = fname;
|
|
}
|
|
m_line = atoi(line.c_str());
|
|
m_msg = msg;
|
|
}
|
|
}
|
|
|
|
script_exception::~script_exception() {
|
|
}
|
|
|
|
char const * script_exception::get_file_name() const {
|
|
lean_assert(get_source() == source::File);
|
|
return m_file.c_str();
|
|
}
|
|
|
|
unsigned script_exception::get_line() const {
|
|
lean_assert(get_source() != source::Unknown);
|
|
return m_line;
|
|
}
|
|
|
|
char const * script_exception::get_msg() const noexcept {
|
|
return exception::what();
|
|
}
|
|
|
|
MK_THREAD_LOCAL_GET_DEF(std::string, get_g_buffer)
|
|
|
|
char const * script_exception::what() const noexcept {
|
|
std::string & buffer = get_g_buffer();
|
|
std::ostringstream strm;
|
|
char const * msg = get_msg();
|
|
char const * space = msg && *msg == ' ' ? "" : " ";
|
|
switch (get_source()) {
|
|
case source::String: strm << "[string]:" << get_line() << ":" << space << get_msg(); break;
|
|
case source::File: strm << get_file_name() << ":" << get_line() << ":" << space << get_msg(); break;
|
|
case source::Unknown: return get_msg();
|
|
}
|
|
buffer = strm.str();
|
|
return buffer.c_str();
|
|
}
|
|
|
|
script_nested_exception::script_nested_exception(source s, std::string f, unsigned l, std::shared_ptr<exception> const & ex):
|
|
script_exception(s, f, l, "Lean exception"),
|
|
m_exception(ex) {
|
|
lean_assert(ex);
|
|
}
|
|
|
|
script_nested_exception::~script_nested_exception() {}
|
|
|
|
char const * script_nested_exception::what() const noexcept {
|
|
std::string super_what = script_exception::what();
|
|
std::string nested_what = get_exception().what();
|
|
{
|
|
std::string buffer;
|
|
std::ostringstream strm;
|
|
strm << super_what << "\n" << nested_what;
|
|
buffer = strm.str();
|
|
std::string & r_buffer = get_g_buffer();
|
|
r_buffer = buffer;
|
|
return r_buffer.c_str();
|
|
}
|
|
}
|
|
}
|