if (!expr) { throw std::runtime_error("unexpected"); }
}
-void handleCError(bool ret, std::exception_ptr *exc = nullptr);
+#ifndef BROKEN_STD_EXCEPTION_PTR
+typedef std::exception_ptr clingo_exception_holder_t;
void handleCXXError();
+#else
+typedef std::shared_ptr<std::string> clingo_exception_holder_t;
+void handleCXXError(const char *what, clingo_error_t err);
+#endif
+
+void handleCError(bool ret, clingo_exception_holder_t *exc = nullptr);
#define GRINGO_CLINGO_TRY try
+
+#ifndef BROKEN_STD_EXCEPTION_PTR
#define GRINGO_CLINGO_CATCH catch (...) { Gringo::handleCXXError(); return false; } return true
+#else
+#define GRINGO_CLINGO_CATCH \
+ catch (Gringo::GringoError const &e) { Gringo::handleCXXError(e.what(), clingo_error_runtime); return false; } \
+ catch (Gringo::ClingoError const &e) { return false; } \
+ catch (Gringo::MessageLimitError const &e) { Gringo::handleCXXError(e.what(), clingo_error_runtime); return false; } \
+ catch (std::bad_alloc const &e) { Gringo::handleCXXError(e.what(), clingo_error_bad_alloc); return false; } \
+ catch (std::runtime_error const &e) { Gringo::handleCXXError(e.what(), clingo_error_runtime); return false; } \
+ catch (std::logic_error const &e) { Gringo::handleCXXError(e.what(), clingo_error_logic); return false; } \
+ catch (...) { Gringo::handleCXXError("", clingo_error_unknown); return false; } \
+ return true
+#endif
// }}}1
}
#ifndef GRINGO_NO_THREAD_LOCAL
- thread_local std::exception_ptr g_lastException;
+ thread_local clingo_exception_holder_t g_lastException;
thread_local std::string g_lastMessage;
thread_local clingo_error_t g_lastCode;
#else
struct TLData {
- std::exception_ptr lastException;
+ clingo_exception_holder_t lastException;
std::string lastMessage;
clingo_error_t lastCode;
};
std::mutex g_tLMut;
std::unordered_map<std::thread::id, TLData> g_tLData;
- std::exception_ptr &tLlastException() {
+ clingo_exception_holder_t &tLlastException() {
std::lock_guard<std::mutex> lock(g_tLMut);
return g_tLData[std::this_thread::get_id()].lastException;
}
} // namespace
-void handleCError(bool ret, std::exception_ptr *exc) {
+void handleCError(bool ret, clingo_exception_holder_t *exc) {
if (!ret) {
+#ifndef BROKEN_STD_EXCEPTION_PTR
if (exc && *exc) { std::rethrow_exception(*exc); }
+#else
+ if (exc && *exc) { throw std::runtime_error(**exc); }
+#endif
char const *msg = clingo_error_message();
if (!msg) { msg = "no message"; }
switch (static_cast<clingo_error>(clingo_error_code())) {
}
}
+#ifndef BROKEN_STD_EXCEPTION_PTR
void handleCXXError() {
try { throw; }
catch (Gringo::GringoError const &) { g_lastException = std::current_exception(); g_lastCode = clingo_error_runtime; return; }
catch (std::logic_error const &) { g_lastException = std::current_exception(); g_lastCode = clingo_error_logic; return; }
g_lastCode = clingo_error_unknown;
}
+#else
+void handleCXXError(const char *what, clingo_error_t err) {
+ g_lastException = clingo_exception_holder_t(new std::string(what));
+ g_lastCode = err;
+}
+#endif
// }}}1
}
#define CLINGO_CALLBACK_TRY try
+
+#ifndef BROKEN_STD_EXCEPTION_PTR
#define CLINGO_CALLBACK_CATCH(ref) catch (...){ (ref) = std::current_exception(); return false; } return true
+#else
+#define CLINGO_CALLBACK_CATCH(ref) catch (std::exception &e){ (ref) = clingo_exception_holder_t(new std::string(e.what())); return false; } return true
+#endif
std::string Symbol::to_string() const {
return ::to_string(clingo_symbol_to_string_size, clingo_symbol_to_string, sym_);
}
void Control::ground(PartSpan parts, GroundCallback cb) {
- using Data = std::pair<GroundCallback&, std::exception_ptr>;
+ using Data = std::pair<GroundCallback&, clingo_exception_holder_t>;
Data data(cb, nullptr);
handleCError(clingo_control_ground(*impl_, reinterpret_cast<clingo_part_t const *>(parts.begin()), parts.size(),
[](clingo_location_t loc, char const *name, clingo_symbol_t const *args, size_t n, void *data, clingo_symbol_callback_t *cb, void *cbdata) -> bool {
SolveResult Control::solve(ModelCallback mh, SymbolicLiteralSpan assumptions) {
clingo_solve_result_bitset_t ret;
- using Data = std::pair<ModelCallback&, std::exception_ptr>;
+ using Data = std::pair<ModelCallback&, clingo_exception_holder_t>;
Data data(mh, nullptr);
handleCError(clingo_control_solve(*impl_, [](clingo_model_t *m, void *data, bool *ret) -> bool {
auto &d = *static_cast<Data*>(data);
} // namespace AST
void parse_program(char const *program, StatementCallback cb, Logger logger, unsigned message_limit) {
- using Data = std::pair<StatementCallback &, std::exception_ptr>;
+ using Data = std::pair<StatementCallback &, clingo_exception_holder_t>;
Data data(cb, nullptr);
handleCError(clingo_parse_program(program, [](clingo_ast_statement_t const *stm, void *data) -> bool {
auto &d = *static_cast<Data*>(data);
extern "C" void clingo_set_error(clingo_error_t code, char const *message) {
g_lastCode = code;
+#ifndef BROKEN_STD_EXCEPTION_PTR
try { g_lastException = std::make_exception_ptr(std::runtime_error(message)); }
+#else
+ try { g_lastException = clingo_exception_holder_t(new std::string(message)); }
+#endif
catch (...) { g_lastException = nullptr; }
}
extern "C" char const *clingo_error_message() {
if (g_lastException) {
+#ifndef BROKEN_STD_EXCEPTION_PTR
try { std::rethrow_exception(g_lastException); }
catch (std::bad_alloc const &) { return "bad_alloc"; }
catch (std::exception const &e) {
g_lastMessage = e.what();
return g_lastMessage.c_str();
}
+#else
+ g_lastMessage = *g_lastException;
+ return g_lastMessage.c_str();
+#endif
}
return nullptr;
}