This PR moves the processing of options passed to the CLI from `shell.cpp` to `Shell.lean`. As with previous ports, this attempts to mirror as much of the original behavior as possible, Benefits to be gained from the ported code can come in later PRs. There should be no significant behavioral changes from this port. Nonetheless, error reporting has changed some, hopefully for the better. For instance, errors for improper argument configurations has been made more consistent (e.g., Lean will now error if numeric arguments fall outside the expected range for an option). (Redo of #11345 to fix Windows issue.)
148 lines
3.6 KiB
C++
148 lines
3.6 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 <iostream>
|
|
#include <sstream>
|
|
#include <set>
|
|
#include <string>
|
|
#include <memory>
|
|
#include <cstdlib>
|
|
#if defined(LEAN_EMSCRIPTEN)
|
|
#include <emscripten.h>
|
|
#endif
|
|
#if !defined(LEAN_WINDOWS)
|
|
// Support for pid
|
|
#include<unistd.h>
|
|
#endif
|
|
#include <lean/lean.h>
|
|
#include "runtime/debug.h"
|
|
|
|
namespace lean {
|
|
static volatile bool g_has_violations = false;
|
|
static volatile bool g_enable_assertions = true;
|
|
static std::set<std::string> * g_enabled_debug_tags = nullptr;
|
|
|
|
void initialize_debug() {
|
|
// lazy initialization
|
|
}
|
|
|
|
void finalize_debug() {
|
|
delete g_enabled_debug_tags;
|
|
}
|
|
|
|
bool has_violations() {
|
|
return g_has_violations;
|
|
}
|
|
// LCOV_EXCL_START
|
|
void enable_assertions(bool f) {
|
|
g_enable_assertions = f;
|
|
}
|
|
|
|
bool assertions_enabled() {
|
|
return g_enable_assertions;
|
|
}
|
|
|
|
void notify_assertion_violation(const char * fileName, int line, const char * condition) {
|
|
std::cerr << "LEAN ASSERTION VIOLATION\n";
|
|
std::cerr << "File: " << fileName << "\n";
|
|
std::cerr << "Line: " << line << "\n";
|
|
std::cerr << condition << "\n";
|
|
std::cerr.flush();
|
|
}
|
|
|
|
void enable_debug(char const * tag) {
|
|
if (!g_enabled_debug_tags)
|
|
g_enabled_debug_tags = new std::set<std::string>();
|
|
g_enabled_debug_tags->insert(tag);
|
|
}
|
|
|
|
/* enableDebug (tag : @& String) : BaseIO Unit */
|
|
extern "C" LEAN_EXPORT lean_obj_res lean_internal_enable_debug(b_lean_obj_arg tag) {
|
|
enable_debug(lean_string_cstr(tag));
|
|
return lean_box(0);
|
|
}
|
|
|
|
void disable_debug(char const * tag) {
|
|
if (g_enabled_debug_tags)
|
|
g_enabled_debug_tags->erase(tag);
|
|
}
|
|
|
|
bool is_debug_enabled(const char * tag) {
|
|
return g_enabled_debug_tags && g_enabled_debug_tags->find(tag) != g_enabled_debug_tags->end();
|
|
}
|
|
|
|
static bool g_debug_dialog = true;
|
|
|
|
void enable_debug_dialog(bool flag) {
|
|
g_debug_dialog = flag;
|
|
}
|
|
|
|
[[noreturn]] void debuggable_exit() {
|
|
abort();
|
|
*((volatile int *) nullptr) = 0;
|
|
}
|
|
|
|
void invoke_debugger() {
|
|
#if defined(LEAN_EMSCRIPTEN)
|
|
EM_ASM(debugger;);
|
|
exit(1);
|
|
#else
|
|
g_has_violations = true;
|
|
if (!g_debug_dialog) {
|
|
throw unreachable_reached();
|
|
}
|
|
for (;;) {
|
|
if (std::cin.eof())
|
|
debuggable_exit();
|
|
#if !defined(LEAN_WINDOWS)
|
|
std::cerr << "(C)ontinue, (A)bort/exit, (S)top/trap\n";
|
|
#else
|
|
std::cerr << "(C)ontinue, (A)bort/exit, (S)top/trap, Invoke (G)DB\n";
|
|
#endif
|
|
char result;
|
|
std::cin >> result;
|
|
if (std::cin.eof())
|
|
debuggable_exit();
|
|
switch (result) {
|
|
case 'C':
|
|
case 'c':
|
|
return;
|
|
case 'A':
|
|
case 'a':
|
|
exit(1);
|
|
case 'S':
|
|
case 's':
|
|
// force seg fault...
|
|
debuggable_exit();
|
|
#if !defined(LEAN_WINDOWS)
|
|
case 'G':
|
|
case 'g': {
|
|
std::cerr << "INVOKING GDB...\n";
|
|
std::ostringstream buffer;
|
|
buffer << "gdb -nw /proc/" << getpid() << "/exe " << getpid();
|
|
if (system(buffer.str().c_str()) == 0) {
|
|
std::cerr << "continuing the execution...\n";
|
|
} else {
|
|
std::cerr << "ERROR STARTING GDB...\n";
|
|
// forcing seg fault.
|
|
debuggable_exit();
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
default:
|
|
std::cerr << "INVALID COMMAND\n";
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
// LCOV_EXCL_STOP
|
|
|
|
extern "C" LEAN_EXPORT void lean_notify_assert(const char * fileName, int line, const char * condition) {
|
|
notify_assertion_violation(fileName, line, condition);
|
|
invoke_debugger();
|
|
}
|
|
}
|