📄 main.cpp
字号:
else
// *add 1.2.1 Interactive Help
if (ppd == "help") show_help("help.txt",Input::next_token(true),'#');
else
if (ppd == "li") Function::lookup(Input::next_token(true))->line_nos()->dump(cmsg);
// *fix 1.2.1 (Eric) Complain if this command is not recognized
else
cerr << '\'' << ppd << "\' is not a command or preprocessor statement" << endl;
return true;
}
/*static*/ int mInteractiveMode = 1;
static string mUCDir;
static char* mPgmName;
bool interactive_mode() { return mInteractiveMode; }
string uc_home_dir() { return mUCDir; }
void bail_out()
{
check_error();
exit(-1);
}
int setup_lib()
{
Parser::init_lib();
return 0;
}
char *uc_get_title()
{ return mUCTitle; }
void Main::initialize()
{
Exception::initialize();
Keywords::init();
Parser::init();
Operators::init();
Expressions::init();
UCTokenStream::init();
#ifdef _WCON
IDE::initialize();
// Non-Interactive
mInteractiveMode = true;
#endif
}
#ifdef _DEBUG
void init_mem_check() // *DEBUG*
{
static bool init = false;
if (! init) {
init = true;
// *DEBUG* Fine control of leak detection
// Get current flag
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
// Turn on leak-checking bit
// tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
// Turn on check-always bit
tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;
tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
// Turn off CRT block checking bit
// tmpFlag &= ~_CRTDBG_CHECK_CRT_DF;
// Set flag to the new value
_CrtSetDbgFlag( tmpFlag );
}
}
int check_mem() // *DEBUG*
{
init_mem_check();
return _CrtCheckMemory();
}
#endif
// *add 1.1.2 Please note that this does NOT work under Linux!
char *Main::uc_exec_name()
{
return mPgmName;
}
string Main::uc_lib_dir()
{
return uc_home_dir() + "/lib/";
}
bool add_include_path(string path)
{
Utils::check_path_end(path);
if (! Utils::can_access(path)) {
error("Cannot find include directory " + path);
return false;
}
TokenStream::set_include_dir(path.c_str());
return true;
}
bool extract_options(int *argc, char **argv, char *opt, char **optstring)
{
char *p = argv[1];
if (p && p[0]=='-') {
*opt = p[1];
*optstring = p+2;
for (int i = 1; i < *argc; i++) argv[i] = argv[i+1];
--(*argc);
return true;
} else return false;
}
// *add 1.2.2 -D adds a preprocessor macro, in the usual way (there must be NO space before the NAME=SUBST)
bool add_prepro_macro(char *str)
{
char *name = strtok(str," =");
if (! name) return false;
char *subst = strtok(NULL," =");
TokenStream::macro_subst(name,subst ? subst : "");
return true;
}
// *add 1.1.4 The -I option will add another include path....
// *add 1.1.4
// Environment var UC_DEFAULT_ARGS can contain extra stuff
// which will be appended to the commmand line passed to UC
// *fix 1.1.4W File names on the WCON command line can now contain spaces
// *change 1.2.0 -O switches off over-allocation
// Pointer check is no longer on by default in release build; use -P.
// -W suppresses dynamic link warnings; it now switches off verbose import information as well.
bool Main::process_command_line(int& argc, char**& argv)
{
char *paths[MAX_INCLUDE_PATHS];
int ipaths = 0;
bool force_interactive = false;
char *inc_path = NULL;
bool use_gtk = false;
char *extra_args = getenv("UC_DEFAULT_ARGS");
Utils::Args args(argc,argv);
args.set_stop_after_file();
if (extra_args && argv) {
argv = args.append_extra_args(extra_args);
}
special_init(&argc,&argv,use_gtk);
// under Win32, we try to deduce where we're called from using argv[0]
#ifdef _WIN32
if (argv != NULL) {
char *progname = argv[0];
mPgmName = strdup(progname);
Utils::strip_last(progname); // strip off the '\ucw.exe'
#ifdef _DEBUG
Utils::strip_last(progname); // strip off the 'wdebug'
Utils::strip_last(progname); // strip off the 'src'
#endif
mUCDir = argv[0];
}
#endif
// UC_HOME is determined by evaluating all of the following. The
// last one that is set is used as the final value.
//
// - the compiled in default
// (under Win32 we get this from argv[0])
// - the UC_HOME environment variable
// - the -H option
// *fix 1.2.8 don't use the UC_HOME macro under Win32; rely on argv[0]
// for the initial guess.
#if defined(UC_HOME) && ! defined(_WIN32)
inc_path = UC_HOME;
#else
// *fix 1.2.9 argv==NULL when this routine is called in the DLL version!
if (argv) mUCDir = argv[0];
#endif
char *t;
if (t=getenv("UC_HOME")) {
// the value set in the environment overrides the compiled in default
inc_path = t; // *fix 1.0.0L bash doesn't like 'UC-INC'
}
string path;
if (inc_path==NULL) {
#ifdef WIN32
path = mUCDir;
#endif
} else {
path = inc_path;
mUCDir = inc_path; // *fix 1.0.0L UC_HOME must override this!
}
if (argv != NULL) {
char opt;
while (args.get_opt(&opt)) {
switch(opt) {
// the command line option overrides any previously set value
case 'H': path = mUCDir = args.get_opt_parameter(); break; // *add 1.1.3 Can override UC_HOME
case 'I':
if (ipaths == MAX_INCLUDE_PATHS) error("Exceeded available include paths");
else paths[ipaths++] = args.get_opt_parameter();
break;
case 'G': use_gtk = true; break;
case 'O': Parser::debug.do_overalloc ^= 1; break;
case 'P': Parser::debug.ptr_check = true; break;
case 'W': Parser::debug.suppress_link_errors = true; break;
case 'D': add_prepro_macro(args.get_opt_parameter()); break;
case 'i': force_interactive = true; break;
case 'F': Parser::debug.attempt_inline = true; break; // *add 1.2.3a New Optimization flag
// *add 1.2.5 run in specified directory
case 'r': Utils::change_dir(args.get_opt_parameter()); break;
// *add 1.2.5 switch on range checking of arrays and vectors
case 'R': Parser::debug.range_check = true; break;
// *add 1.2.6 Outputing version and help
//* #ifdef _CONSOLE
case 'v': cout << "UnderC " << mUCVersion << endl; return false;
case '-':
if (strcmp(args.get_opt_parameter(),"help")==0)
{
show_help("cmd-help.txt",NULL,'-');
return false;
}
break;
// *add 1.2.9 Evaluating expressions from the command-line
case 'e':
uc_eval(args.get_opt_parameter(),true,true);
exit(0);
break;
//* #endif
// *add 1.2.6 These are also available as #opt parameters
case 'T': Parser::debug.use_typedef_names = true; break;
case 'S': Parser::debug.skip_method_bodies = false; break;
default: cerr << "unrecognized option: " << opt << endl; return false;
}
}
if (Parser::debug.range_check) add_builtin_macro("_RANGE_CHECK");
}
// *change 1.2.2b The Windows GUI build is _always_ interactive, and the console
// build is interactive if (a) there are no args or (b) forced with the -i option.
#ifdef _WCON
mInteractiveMode = force_interactive || argc == 1; // true;
#else
mInteractiveMode = force_interactive || argc == 1;
#endif
Utils::check_path_end(path);
path += "include";
if (! add_include_path(path)) return false;
// NOW we may add the extra paths, if any
for(int i = 0; i < ipaths; i++)
add_include_path(paths[i]);
return true;
}
void Main::banner()
{
#ifdef _WCON
wcon_set_size(20,50,600,500);
wcon_set_title(mUCTitle);
wcon_prompt_char(';',0);
#endif
cmsg << "UnderC C++ Interpreter vs " << mUCVersion << endl;
cmsg << "Steve Donovan, 2001-2003" << endl;
cmsg << "This program is GPL'd; see LICENCE for details" << endl;
}
void Main::finalize()
{
// *add 1.2.3 Destroy any statically allocated objects
Engine::global_unwind();
// and unload any DLLs
Builtin::finis();
#ifdef _WCON
// *add 1.2.8 inform the IDE that we're going down...
IDE::ucw_shut_down();
#endif
}
int Main::interactive_loop()
{
for(;;) {
if (call_parser()==FAIL) {
//* if (! interactive_mode()) return -1;// bail out if in batch mode
} else return 0;// successful exit!
}
}
////////// MAIN ///////////////
#ifndef _USRDLL
int main(int argc, char **argv)
#else
int pgm_main(int argc, char **argv)
#endif
//----------------------------
{
using namespace Main;
initialize();
// *fix 1.2.3 Suppress irritating warning until we can decide what to do here!
if (! process_command_line(argc, argv)) return 0;
if (interactive_mode()) {
banner();
Input::open("CON");
Input::set_open_restore(NULL,setup_lib);
const char* defs_file = (argc > 1) ? argv[1] : "defs.h";
if (!Input::open(defs_file)) {
cmsg << "Now opening defs.h in UC home directory" << endl;
string uc_home = uc_home_dir();
Utils::check_path_end(uc_home);
string default_defs = uc_home + "defs.h";
if (! Input::open(default_defs.c_str())) check_error();
}
} else {
// *add 1.2.9 Important to call these before/after routines
// for initialization/finalization code to work properly.
// *change 1.2.9a old behaviour
set_on_open_restore(false);
if (! Input::open(argv[1])) bail_out();
}
// keep going until we end successfully!
int retval = interactive_loop();
if (retval == -1) return retval;
if (! interactive_mode()) {
mInteractiveMode = true; // to force statement_end() to evaluate!
Parser::init_lib(); // *fix 1.1.0 force any library initializations
retval = Program::call_main(argc-1,argv+1,Program::new_window);
}
finalize();
return retval;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -