⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 UC Library Extensions UnderC comes with a pocket implementation of the standard C++ libraries, wh
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* main.cpp
 * Main Program, initialization, and # command implementation
 * UnderC C++ interpreter
 * Steve Donovan, 2001
 * This is GPL'd software, and the usual disclaimers apply.
 * See LICENCE
 */
#include <ctype.h>
#include <stdio.h>
#include "common.h"

#include "breakpoints.h"
#include "module.h"
#include "tokens.h"
#include "engine.h"
#include "mangle.h"
#include "directcall.h"
#include <time.h>
#include "keywords.h"
#include "operators.h"
#include "uc_tokens.h"
#include "program.h"
#include "utils.h"
#include "input.h"
#include "version.h"
#include "errors.h"
#include "hard_except.h"
#include "main.h"
#include "config.h"
#include "loaded_module_list.h"

#ifdef _WCON
#include "ide.h"
#endif

// *DEBUG*
#ifdef _DEBUG
#include <crtdbg.h>
int check_mem(); //  *DEBUG*

// *add 1.2.8 A debug interface for assisting the poor debuggers of UC
int gDebugBreak = 0;
FBlock* gFunBlock = 0;
void __break(int);
#else
int check_mem() 
{
  return 1;  
}

#endif

void dump_fun_stack(); // in engine.cpp

int yyparse(); // found in TPARSER.CPP (generated by Bison from parser.y)
bool check_error();  // ditto
void clear_global_namespace();  // in table.cpp

void dump_module_traceback(); // in uc_tokens.cpp

#ifdef BUILD_WITH_GTK 
void special_init(int *argc, char ***argv, bool on_off);  // found in UCW_GTK
#else
void special_init(int *argc, char ***argv, bool on_off) { }
#endif

void macro_cleanup(); // in tokens.cpp (backdoor!!)
void add_builtin_macro(const char* name); // in uc_tokens.cpp (ditto, I suppose)

const int EXPR_BUFF_SIZE = 1024, PATHSIZE = 256;

// *hack 1.2.2b The console version experiences a most odd problem
// when running a program occaisionally. yylex() returns 0, but yyparse()
// considers this an error, and gives us a characteristic 'DUD' error message.
// To get around this, the console version shuts down by _throwing an int_
int call_parser()
{
  try {
    if (yyparse()==1) { // an error occured!
       Input::clear();
       return FAIL; 
    } else 
	   return OK; // successful exit!
  } catch(int) {
#ifndef _WCON
    //cerr << "DUD err" << endl;
#endif
    return OK;
  }
}

int uc_eval(char *expr, bool append_semicolon=true, bool synchronous=false, char *name=NULL, int lineno=0)
{
 static char buffer[EXPR_BUFF_SIZE];
 char *ibuff = synchronous ? new char[strlen(expr)+10] : buffer;
 strcpy(ibuff,expr);
 if (append_semicolon) strcat(ibuff,";");
 if (synchronous) strcat(ibuff,"\n#q");
 //cout << "*ibuff " << ibuff;
 Parser::state.lineno = 0;   // reset error state and go for it...
 Parser::state.file = "";
 bool old_compile_flag = Parser::debug.compile_program;
 Parser::debug.compile_program = false;
 Input::insert_stream(new istrstream(ibuff),name ? name : "$EXPR",lineno);
 if (synchronous) { 
     int ret = call_parser();
     delete ibuff;
     Parser::debug.compile_program = old_compile_flag;
     if (ret == OK) { 
         if (Engine::paused()) return HALTED;
         if (Parser::state.lineno > 0) return CRASHED;
     }
     return ret;
 } 
 else {
  Parser::debug.compile_program = old_compile_flag;
  return PENDING;
 }
}

// *change 1.2.8 May be passed an optional (file,position) for
// incremental compilation.  In this mode, we force compilation
// to occur in global context.
int redirected_eval(char *s, bool do_semi, char *name=NULL, int lineno=0)
{
  Table* tbl = &Parser::state.context();
  bool pushing_context = false;
  if (name != NULL && tbl != &Parser::global()) {
      Parser::state.push_context(&Parser::global());
      pushing_context = true;
  }
// synchronous execution
  Errors::redirect_output(true);
  int ret = uc_eval(s,do_semi,true,name,lineno);
  Errors::check_output(); // make sure errors & messages no longer redirected
  if (pushing_context) {  // restore context
      Parser::state.pop_context();
      if (ret == HALTED) ret = OK;  // engine state was halted; no problem
  }
  return ret;
}

void save_parser_state();
void restore_parser_state();

// *add 1.2.4 exported as uc_exec()
int _uc_exec(char* s, void* cntxt, char* filename, int line)
{
  string file;
  int lineno;
  // protect the temporary code block from being trashed
  Instruction* immed_code = Parser::immediate_code_ptr();
  Parser::immediate_code_ptr(NULL); 
  // redirect errors and messages
  Errors::reset_error_state();
  Errors::redirect_output(true);

  // keep old parser state for later
  Parser::ParserState old_state = Parser::state;
  dcl_set(false,false); // save the DCL & ALS stacks...
  save_parser_state();  // save the BISON state...

  // do the compilation/evaluation, using the context if requested.
  if (cntxt) Parser::state.push_context((Table*)cntxt);
  int ret = uc_eval(s,false,true,filename,line);
  if (cntxt) Parser::state.pop_context();

  // reset parser state, but make sure the error state is kept!
  file = Parser::state.file;
  lineno = Parser::state.lineno;
  restore_parser_state();
  dcl_reset();
  Parser::state = old_state;
  Parser::state.file = file;
  Parser::state.lineno = lineno;
  // make sure errors & messages no longer redirected
  Errors::check_output(); 
  Parser::immediate_code_ptr(immed_code);
  return ret;
}

// *add 1.2.4 exported as uc_result()
void _uc_result(int ret, char *output, int sz, char* filename, int* line)
{
  char *out;
  if (ret==OK) out = Errors::get_redirect_buffer(1);
  else out = Errors::get_redirect_buffer(2);
  strncpy(output,out,sz);
  if (filename) {
    *line = Errors::get_stop_position(filename);
  }
}

int ext_uc_eval(char *expr, char *output, int sz)
{
  int ret = redirected_eval(expr,true);
  _uc_result(ret,output,sz,0,0);
  return ret;
}

bool s_single_step = false;
static char* gCurrentArgs = "";

int ext_run_program(char *cmdline, int stepping)
{
 Errors::redirect_output(true,false);
 char buff[256];
 strcpy(buff,cmdline);
 if (stepping) { Engine::set_single_stepping(stepping == 1); } // *HACK*
 if (Program::run(buff)) return 0;  // main() not found!
 else return 1;
}

bool insert_input_file(char *filename)
{
  ifstream *pfs = new ifstream(filename,IOS_IN_FLAGS); 
  if (!(*pfs)) {
        delete pfs;
        return false;
  }
  Input::insert_stream(pfs,filename);
  return true;
}

int safe_atoi(char *str)
{ 
  return str==NULL ? 0 : atoi(str);
} 

bool command_error(char *msg, char *sym=NULL)
{
  cerr << msg;
  if (sym != NULL) cerr << '\'' << sym << '\'';
  cerr << endl;
  return true;
}

bool cant_open_err(char *cfile)
{ return command_error("Cannot open",cfile); }

bool cant_find(char *name)
{  return command_error("Cannot find",name); }


static char *TMPFILE = "_tmp010_u.txt";

void uc_system(char *cmd)
{
#ifndef _WCON
  system(cmd);
#else
  int exec(char *msg, int cshow, bool do_wait);
  const int BUFFSIZE = 200;
  char buff[BUFFSIZE];
  // The idea here is to direct output to a temporary
  // (if not already redirecting!) and dump this file.
  string spath = getenv("COMSPEC");   // Win32 warning...
  string cmdl = spath + " /c " + string(cmd);
  bool redirect_stdout = cmdl.find(">") == -1;
  if(redirect_stdout) { cmdl += " > "; cmdl += TMPFILE; }
  exec(cmdl.c_str(),0,true);
  if(redirect_stdout) {
    ifstream inf(TMPFILE,IOS_IN_FLAGS);
    if (!inf) return;
    while (!inf.eof()) {
      inf.getline(buff,BUFFSIZE);
      puts(buff);
     }
  }
#endif
}

char *get_temp_log()
{
 static char buff[30];
 struct tm *ts;
 time_t t;
 time(&t);
 ts = localtime(&t);
 ts->tm_mon++;  
 sprintf(buff,"%02d%02d-%02d%02d",ts->tm_mon,ts->tm_mday,ts->tm_hour,ts->tm_min);
 return buff;
}

// *add 1.2.1 Getting interactive help
string uc_home_dir(); // forward

void show_help(char* help_text, char* cmd, char marker)
{
    char buff[256];
    string help_file = uc_home_dir()+"/";
    help_file += help_text;
    ifstream in(help_file.c_str(),IOS_IN_FLAGS);
    if (! in) { cerr << "cannot find " << help_file << endl; return; }
    if (cmd && *cmd == marker) cmd++;
    while (! in.eof()) {
      in.getline(buff,sizeof(buff));
      if (buff[0] == marker) {
       if (! cmd) cmsg << buff << endl;
       else {         
         if (strncmp(cmd,buff+1,strlen(cmd))==0) {
            buff[0] = ' ';
            while (buff[0] != marker) {
                cmsg << buff << endl;
                in.getline(buff,sizeof(buff));
            }
         return;
         }
       }
      }
    }  
}
//* #endif

// *change 1.2.8 added more control on whether one wants the contents of the parent 
// context as well.
void display_locals(Table *tbl, void *pobj, bool is_ptr = false, bool do_all = false)
{
// *add 1.1.2 Will dereference a pointer or reference variable
  const int LOCALBUFF = 1024;
  char buff[LOCALBUFF];
  bool pushing_context = tbl != NULL;
  if (!pushing_context) tbl = &Parser::state.context();
  else {
      Parser::state.push_context(tbl);
	  if (is_ptr) pobj = *(void **)pobj;
      Engine::object_ptr(pobj);
  }
  ostrstream os(buff,LOCALBUFF);
  int flags = Table::SEMICOLON_SEP | Table::VARS;
  if (do_all) flags |= Table::ALL;
  tbl->dump_entries(os,flags);
  os << ends;
  
  Parser::debug.no_access_control = true;
  uc_eval(buff,false,true);
  Parser::debug.no_access_control = false;
  if (pushing_context) Parser::state.pop_context();
}

/// These guys bracket every LOAD operation; the idea here
/// is to clean up any namespace pollution so that
/// the module compilation won't be bothered.  Afterwards,
/// the crud is put back in.
/// *add 1.2.0 Any files with extension ".c" are loaded in C-mode
/// *add 1.2.3 Ditto, files with extension .c, .cpp or .cxx loaded in _strict mode_
/// This will attempt to enforce the standard language as much as possible.
/// *add 1.2.9 Managing the program ODL (Object Destructor List)
/// The basic assumption around here is that compile_module() is _not_ reentrant;
/// e.g. using #l within a file loaded with #l is not guaranteed to work properly.

static bool s_last_c_mode, s_last_strict_mode, s_is_cpp_source = false, s_is_conditional;

// only called if the file could be opened...

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -