📄 main.cpp
字号:
int module_open()
{
string ext = Utils::file_extension(Module::current()->name());
s_is_cpp_source = ext == ".c" || ext == ".cpp" || ext == ".cxx";
s_last_c_mode = Parser::debug.c_mode;
s_last_strict_mode = Parser::debug.strict;
if (ext == ".c") Parser::set_c_mode(true);
Parser::debug.strict = s_is_cpp_source;
Parser::debug.compile_program = s_is_cpp_source;
Module::clean_namespaces();
Module* pm = Module::current();
pm->clean_macros_and_typedefs();
// *change 1.2.9a Plain #l works as before; #lc creates __init functions etc.
s_is_cpp_source = s_is_cpp_source && s_is_conditional;
LoadedModuleList::init_module(s_is_cpp_source? pm->id() : -1);
return 0;
}
// should always called!
int module_close()
{
using namespace Parser;
if (s_is_cpp_source ) {
Instruction* pi;
if (code().total_instructions() > 0) {
code().emit_return(t_void);
pi = code().end_code();
} else pi = NULL;
LoadedModuleList::finish_module(pi);
}
s_is_cpp_source = false;
Module::restore_namespaces();
Parser::set_c_mode(s_last_c_mode);
Parser::debug.strict = s_last_strict_mode;
Parser::debug.compile_program = false;
return 0;
}
static void set_on_open_restore(bool is_conditional)
{
s_is_conditional = is_conditional;
Input::set_open_restore(module_open,module_close);
}
extern Function* gLastFunction; //*DEBUG - found in common.cpp
void __mangle()
{
cerr << '_' << Mangle::GCC3(gLastFunction) << ';' << endl;
}
enum {CANT_OPEN, FILE_UNCHANGED, SUCCESS};
int compile_module(char *file, bool is_conditional)
{
// *fix 1.2.8 Make sure we're in global context before attempting a compilation
bool is_break = Parser::current_function() != NULL;
if (is_break) Parser::state.push_context(&Parser::global());
// *add 0.9.8 #l should now do a dependency check to allow changed headers to be included...
Module *pm = Module::from_name(file);
if (!is_conditional) {
if (pm != NULL) {
Module::reset_modify_flags();
// should we _always_ reload with #l?
if (! pm->needs_rebuilding()) return FILE_UNCHANGED;
}
} else if (pm != NULL && ! pm->needs_rebuilding()) return FILE_UNCHANGED;
//*DEBUG*
if (is_conditional) {
cmsg << "load: " << file;
if (pm != NULL) cmsg << " id = " << pm->id();
cmsg << endl;
}
set_on_open_restore(is_conditional);
Parser::state.reset();
if (is_break) Parser::state.pop_context();
return Input::open(file) ? SUCCESS : CANT_OPEN;
}
int yylex(); // further along here...
extern bool tok_dbg;
bool UCTokenStream::user_cmd(string ppd)
{
static string current_file;
if (ppd == "q") return false; else
#ifdef _WCON
if (ppd == "ql") {
wcon_copy_to_log(get_temp_log());
return false;
} else
#endif
// *add 1.1.2 #pragma! Just dlink and pack()
// *fix 1.2.0 it's not an error to leave out the library name
if (ppd == "pragma") {
char *line = get_upto(0,false);
string what = strtok(line," ()");
char *arg = strtok(NULL," ()");
if (what == "dlink") {
if (!Builtin::set_current_lib_file(arg)) return cant_open_err(arg);
char *impf = strtok(NULL," ()");
if (impf != NULL) Builtin::generate_ordinal_lookup(impf);
} else
if (what == "pack") Parser::set_alignment(atoi(arg));
#ifdef _DEBUG
else
if (what == "break") {
gDebugBreak = atoi(arg);
if (gDebugBreak == 1) {
__break(1);
gDebugBreak = 0;
}
}
#endif
} else
if (ppd == "x") uc_system(get_upto(0,false)); else
if (ppd == "cd") {
Utils::change_dir(Input::next_token(true));
} else
if (ppd == "pwd") {
cmsg << Utils::get_curr_dir() << endl;
} else
if (ppd == "l" || ppd == "lc") {
Errors::reset_error_state();
char *cfile = Input::next_token();
if (cfile) current_file = cfile;
else if (current_file[0] != '\0') cfile = current_file.c_str();
else return command_error("Please supply file\n");
bool condn = ppd == "lc";
int ret = compile_module(cfile,condn);
if (ret == CANT_OPEN && !condn) cant_open_err(cfile);
else if (ret == FILE_UNCHANGED) cmsg << "unchanged\n";
} else
if (ppd == "bl") {
// *add 0.9.4 Use this before a series of #lc commands...
Module::reset_modify_flags();
} else
// *add 1.2.8 the #args command can be used to set commmand-line args for debugging;
// after #args, the #r commands will use it as the default, unless overriden.
if (ppd == "r" || ppd == "rx" || ppd == "args") {
char* args = get_upto(0,false);
if (ppd=="args") gCurrentArgs = strdup(args);
else { // run the program (rx means 'don't run in separate thread'
if (*args == '\0' && gCurrentArgs != NULL) args = strdup(gCurrentArgs);
if (!Program::run(args,ppd=="rx")) cant_find("main");
}
} else
#ifdef _WCON
if (ppd == "log") {
wcon_copy_to_log(Input::next_token());
} else
#endif
if (ppd == "lib") {
char *libf = Input::next_token();
if (!Builtin::set_current_lib_file(libf)) cant_open_err(libf);
char *impf = Input::next_token(false);
// *fix 1.2.5 we were attempting to read an ordinal file after an empty #lib
if (libf) {
if (impf != NULL) Builtin::generate_ordinal_lookup(impf);
}
} else
if (ppd == "opt") {
char *line = get_upto(0,false);
char *opt = strtok(line,", ");
while (opt) {
char ch = *opt++;
bool is_on = *opt == '+';
bool strip_prompt, block_ide, change_block_ide = false;
switch(ch) {
case 'u': Parser::debug.auto_dissemble = is_on; break;
case 'd': Parser::debug.dump_expr = is_on; break;
case 'x': Parser::debug.auto_exec = is_on; break;
case 't': Parser::debug.function_trace = is_on; break;
case '4': Parser::debug.class_dword_align = is_on ? 4 : 1; break;
case 'v': Parser::debug.verbose = is_on; tok_dbg = is_on; break;
case 's': Parser::debug.strict = is_on; break;
case 'p': Parser::debug.ptr_check = is_on; break;
case 'a': Parser::debug.no_access_control = is_on; break;
case 'c': strip_prompt = is_on; break;
case 'q': block_ide = is_on; change_block_ide = true; break;
case 'C': Parser::set_c_mode(is_on); break;
case 'T': Parser::debug.use_typedef_names = is_on; break;
case 'L': Parser::debug.suppress_link_errors = is_on; break;
case 'i': Parser::debug.interactive_debugging = is_on; break;
case 'S': Parser::debug.no_trace_std = is_on; break;
case 'e': Parser::debug.errors_as_break = is_on; break;
case 'R': Parser::debug.range_check = is_on; break;
// temporary debugging options go here...
}
opt = strtok(NULL,", ");
#ifdef _WCON
// defaults initially to being on....
if (strip_prompt) wcon_prompt_char(';',0);
else wcon_prompt_char(0,0);
if (change_block_ide) IDE::set_blocking(block_ide);
#endif
}
} else
if (ppd == "lv") {
display_locals(NULL,NULL,false,Input::next_token() != NULL);
} else
// *add 1.2.8 #dl <obj> shows only _local_ fields, not inherited as well.
if (ppd == "d" || ppd == "dl") {
PEntry pe = Input::lookup_next_symbol();
if (pe == NULL) return cant_find("symbol");
Type t = pe->type;
if (!t.is_class()) return command_error("Not an object");
void *ptr = pe->global_ptr();
display_locals(t.as_class(),ptr,t.is_ref_or_ptr(), ppd == "d");
} else
if (ppd == "rm") { // remove symbol or program
PEntry pe = Input::lookup_next_symbol();
if (pe->type.is_function()) { // this was a function
if (pe->name=="main") Breakpoint::remove_all(); // *add 0.9.8 remove program and clear out breakpoints
FunctionEntry* pfe = reinterpret_cast<FunctionEntry *>(pe->data);
int imod = pfe->back()->line_nos()->module();
Module *pm = Module::from_id(imod);
if (pm != NULL) Module::remove(pm);
}
if (pe == NULL) return cant_find("symbol");
Parser::global().remove(pe);
} else
if (ppd == "s") { // *add 0.9.4 Now can stop runaway programs w/ #s
#ifdef _WCON
Program::stop_main(false); // *change 1.2.8 no longer an error
#endif
} else
if (ppd == "st" || ppd == "sto") { // *add 1.1.4 Single-stepping through programs!
s_single_step = true;
Engine::set_single_stepping(ppd == "st");
Program::run(gCurrentArgs,false /*Input::next_token() == NULL*/);
} else
if (ppd == "clr") { // clear input (0) or console (1)
#ifdef _WCON
wcon_clear(safe_atoi(Input::next_token()));
#endif
// otherwise need some portable way of doing clr 0?
} else
if (ppd == "attach") {
// char *fn = Input::next_token();
// attach_main_context(fn);
} else
if (ppd == "mod") {
char *fun = Input::next_token();
if (fun == NULL) Module::dump_entries(cmsg,0);
else {
// Module *pm = Module::from_name(file);
// if(pm == NULL) cant_find(file);
// else pm->dump(*msg,Module::FUNS | Module::DEPEND);
string file;
// *change 0.9.4 #mod name gives defn pos. of function 'name'
int ln = Module::file_from_function(Function::lookup(fun),file);
cmsg << file << ' ' << ln << endl;
}
} else
if (ppd == "types" || ppd == "funs") {
char *pat = Input::next_token();
EntryList el;
if (pat == NULL) pat = "*";
Parser::global().search_entries(pat,&el,(ppd == "funs") ? FUNCTIONS : (CLASSES | NAMESPACES | TYPEDEFS));
EntryList::iterator eli;
FORALL(eli,el) cmsg << (*eli)->name << endl;
} else
if (ppd == "gt" || ppd == "b") {
Errors::reset_error_state();
int lineno = safe_atoi(Input::next_token());
char *file = Input::next_token(false);
if (file == NULL) file = current_file.c_str(); // set by #l, etc
//cout << "b " << file << ':' << lineno << endl;
Breakpoint::toggle(file,lineno,ppd == "b",cmsg);
} else
if (ppd == "bs") { // set a number of breakpoints in a file
Errors::reset_error_state();
char *tok, *file = Input::next_token();
int lines[10], i = 0;
while ((tok = Input::next_token(false)) != NULL)
lines[i++] = safe_atoi(tok);
if (i == 0) { // this is a _request_!!
Breakpoint::group(file,lines,i,true);
cmsg << i << ' ';
for (int k = 0; k < i; k++) cmsg << lines[k] << ' ';
cmsg << endl;
} else
Breakpoint::group(file,lines,i,false);
} else
if (ppd == "ff") {
Engine::set_frame(safe_atoi(Input::next_token(true)),true);
if (! Parser::debug.interactive_debugging)
display_locals(NULL,NULL);
} else
if (ppd == "fs") {
dump_fun_stack();
}
else
if (ppd == "u" || ppd == "mm" || ppd == "fe") {
// char *name = next_token();
PEntry pe = Input::lookup_next_symbol();
if (pe == NULL) return true;
int idx = safe_atoi(Input::next_token(true));
if (pe->type.is_function()) {
if (ppd == "u") Parser::dump_function(pe,true,idx,cout);
else {
Function *pf = *(((FunctionEntry *)pe->data)->begin());
if (ppd == "fe") {
FBlock *fb = pf->fun_block();
fb->nlocal = idx;
} else {
// cout << "MS: " << Mangle::microsoft(pf) << endl;
cout << Mangle::GCC3(pf) << endl;
}
}
}
} else
if (ppd == "v") { // inspect - used to be 'var'!!
PEntry pe = Input::lookup_next_symbol();
if (pe==NULL) return true;
Parser::dump_var(pe);
} else
if (ppd == "tx") { //*TEST*
redirected_eval(get_upto(0,false),false);
}
else
if (ppd == "rx") { //*TEST*
ext_run_program(get_upto(0,false),false);
}
else
if (ppd == "vmt") {
PEntry pe = Input::lookup_next_symbol();
if (pe == NULL) return true;
Type t = pe->type;
int *ptr = *(int **)pe->global_ptr();
ptr--; // now at hidden pointer...
PClass pc = t.as_class();
if (! pc->has_VMT()) cout << "No VMT\n";
cout << "name " << pc->name() << " " << pc->last_slot() << endl;
for(int i = 1; i < pc->last_slot(); i++) {
cout << i << ' ';
((Function *)ptr[i])->dump(cout);
cout << endl;
}
}
else
if (ppd == "unload") {
Builtin::unload_lib(Builtin::get_dll_handle());
}
else
if (ppd == "mc") { macro_cleanup(); clear_global_namespace(); }
else
if (ppd == "unwind") { Engine::global_unwind(); }
else // *add 1.2.9 Module trace back list
if (ppd == "trace_back") { dump_module_traceback(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -