📄 common.cpp.svn-base
字号:
/* common.cpp
* Support logic for grammar
* UnderC C++ interpreter
* Steve Donovan, 2001
* This is GPL'd software, and the usual disclaimers apply.
* See LICENCE
*/
#include "common.h"
#include "function_match.h"
#include "tparser.h"
#include "code.h"
#include "opcodes.h"
#include "engine.h"
#include "directcall.h"
// for Module stuff.....
#include "module.h"
#include "input.h"
#include "tokens.h"
Table* gScopeContext;
#ifdef _DEBUG
extern int gDebugBreak;
extern FBlock* gFunBlock;
void __break(int);
#endif
Function* gLastFunction; //*DEBUG
void* gObjectReturnPtr;
void next_statement(); // in uc_tokens.cpp
void skip_function_body(int brace_count=1); // *TEMP* in templates.cpp
// these are temporary places for stuff that must go in headers!
void dissemble(PFBlock fb); // in DISSEM
void dissembler_init();
bool interactive_mode();
// found in parser code - don't muck w/ in_declaration directly!
extern bool IEF;
void force_comma_flag();
// found in type.cpp (of all places!)
Signature *unique_signature(Signature *sig);
void *Entry::global_ptr()
{
return Parser::global().addr(data);
}
char *Entry::object_ptr(char *obj)
{
return obj + data;
}
// *add 1.1.4 Bit field management. Note the assumption here is that
// for a 32-bit word, the info can be packed into 20-bits, which is
// the operand size for our instruction set.
struct _BitField {
int offs; //: 10;
int bit_offs; //: 5;
int bit_size; //: 5;
int rest; // : 12; // pack up to 32-bits
};
void Entry::set_bit_field(int offs, int bit_offs, int bit_size)
{
int sz = sizeof(_BitField);
data = Parser::global().alloc(sz,NULL);
rmode = OREL_F;
_BitField *bf = (_BitField *)Parser::global().addr(data);
bf->offs = offs;
bf->bit_offs = bit_offs;
bf->bit_size = bit_size;
bf->rest = 0;
// unsigned int rdata;
// memmove(&rdata,&bf,4);
// data = rdata;
}
void unpack_bitfield(int data, int& offs, int& bit_offs, int& bit_size)
{
_BitField *bf = (_BitField *)Parser::global().addr(data);
offs = bf->offs;
bit_offs = bf->bit_offs;
bit_size = bf->bit_size;
}
void Entry::get_bit_field(int& offs, int& bit_offs, int& bit_size)
{
unpack_bitfield(data,offs,bit_offs,bit_size);
}
string itos(int i)
{
char buff[20];
itoa(i,buff,10);
return buff;
}
string as_str(Type t)
{ static string str;
t.as_string(str);
return str;
}
void fail(const string& msg)
{
throw msg;
}
//... private to this module
namespace {
const int DATA_SIZE = 1000000;
Global mGlobal(DATA_SIZE);
FBlock mCodeBlock;
LocalContext *mpTempContext=NULL;
PClass mCatchHandlerObj=NULL;
const int CONTINUEABLE = 1, IN_METHOD = 2, CONTEXT_PUSHED = 4,
IN_SWITCH = 8, BREAKABLE = 16, FUN_BLOCK = 32, LOOP_SCOPE = 64;
}
//.......................
void clear_global_namespace()
{
mGlobal.clear();
}
int yyerror(const char *s);
void error(string msg)
{
using Parser::state;
// this flag forces an orderly exit from the parser!
if (state.err != "") yyerror(state.err.c_str());
state.err = msg;
state.file = Input::filename();
state.lineno = Input::lineno();
}
void warning(string _msg)
{
cmsg << Input::filename() << ' ' << Input::lineno() << ": "
<< _msg << endl;
}
string make_temp_name()
{
static int k = 0;
return "$" + itos(k++);
}
int tstack_depth()
{ return Parser::state.tstack.depth(); }
static Parser::ExprFun s_expr_handler;
// shared w/ parser,for the mo!
namespace Parser {
ParserState state;
PEntry mEIntDivByZero=NULL,mEAccessViolation=NULL,mEFloatDivByZero=NULL,
mEException=NULL,mERangeError=NULL;
PExpr mOCout=NULL;
PExpr mObjectReturnExpr;
Namespace* sStdNamespace = NULL;
int s_array_size = 1;
int s_twodim_array = 1;
DebugFlags debug;
Global& global() { return mGlobal; }
Table* std_namespace()
{
return (Table*) sStdNamespace;
}
bool set_alignment(int ipack)
{
if (ipack != 1 && ipack != 4 && ipack != 8) return false;
Parser::debug.class_dword_align = ipack;
return true;
}
// temporary stuff used by the grammar to Express Itself.
void out(char *s)
{ cout << s; }
void outln(char *s)
{ cout << s << endl; }
string quotes(const string& s)
{ return "'" + s + "'"; }
// type stack stuff
void tpush(Type t)
{
state.tstack.push(t);
if (state.tstack.depth() >= state.tstack.capacity())
state.tstack.pop();
}
Type& tots()
{ return state.tstack.TOS(); }
void stots(TType tt)
{ state.tstack.TOS() = AsType(tt); }
Type tpop()
{ return state.tstack.pop(); }
TType ttots()
{ return AsTType(tots()); }
TType make_ref(TType t)
{ AsType(t).make_reference(); return t; }
TType incr_ptr(TType t)
{ AsType(t).incr_pointer(); return t; }
TType make_unsigned(TType t)
{ AsType(t).make_unsigned(); return t; }
int block_depth()
{
return state.block_stack.depth();
}
void *ExprToPtr(Expression e)
{
// *SJD* This is specialized to operate with _globally allocated_ data
if (!e->is_entry()) return NULL;
return e->entry()->global_ptr();
}
// *fix 1.2.3a (Eric) Can now have expressions as array sizes
TType make_array(TType t, Expression psz)
{
int sz=0; // defaults to zero so we know to infer size from initializer...
if (psz) {
try { sz = const_int_expr(psz); }
catch(string msg) { error(msg); return t; }
}
AsType(t).make_array(sz);
if (s_array_size > 1) s_twodim_array = sz;
else s_array_size = sz;
return t;
}
void reset_array_size()
{
s_array_size = 1; //*SJD* Temporary hack!
s_twodim_array = 1;
}
LocalContext *temp_context()
{ return mpTempContext; }
PClass try_block_class()
{ return mCatchHandlerObj; }
void set_function_code(bool is_fn)
{
state.m_PCode = is_fn ? &state.m_FContext : &state.m_SContext;
}
UCContext& static_code() { return state.m_SContext; }
bool is_function_code() { return state.m_PCode == &state.m_FContext; }
UCContext& code() { return *state.m_PCode; }
FBlock *temp_fun_block() { return &mCodeBlock; }
// support code for grammar starts here....
bool is_class(Table *pc) { return pc->type()==IS_STRUCT; }
bool is_namespace(Table *pc) { return pc->type()==IS_NAMESPACE;}
bool in_class_context() { return is_class(&state.context()); }
bool is_local(Table *fc) { return fc->type()==FUNCTION;}
bool is_class_entry(PEntry pe)
{ return in_class_context() && pe == PClass(&state.context())->entry(); }
bool is_global(Table* pc) { return pc == &mGlobal; }
bool is_global_entry(PEntry pe) { return is_global(pe->context);}
Function *current_function(Table *context)
{
if (context==NULL) context = &state.context();
if (is_local(context)) return PLocalContext(context)->function();
else return NULL;
}
int a;
PEntry symbol_lookup(const string& name)
{
Table *context = &state.context() ;
PEntry pe = context->lookup(name);
if (!pe) return NULL;
if (debug.no_access_control) return pe;
if (!is_class(pe->context)) {
return pe; // interactive!!
}
// Access control - this entry came from a class....
PClass pe_class = (Class *)pe->context;
// if we are in a function, see if it is a friend!
Function *function = current_function(context);
if (function && pe_class->is_friend_function(function)) return pe;
// What is our current class context?
PClass this_class;
if (is_class(context)) this_class = (Class *)context; else
if (function) this_class = function->class_context();
else this_class = NULL;
if (this_class == pe_class) return pe; // trivial case!
int access = pe->access(), base_access = pe_class->base_access_mode();
if (base_access != Public) {
if (base_access == Private) access = Private; else
if (base_access == Protected && access == Public) access = Protected;
}
if (access==Public) return pe;
if (this_class) {
if (access == Protected && this_class->inherits_from(pe_class)) return pe;
if (pe_class->is_friend_class(this_class)) return pe;
//*SJD* Does this entry come from an _enclosing_ class?
// (can tell this if we do have the right parent but it isn't a base class!)
if (this_class->parent_context() == pe_class && this_class->base_class()==NULL)
return pe;
}
// sorry, no can do.
warning("cannot access " + quotes(pe->name));
return pe; ///NULL; *Behaviour is different in 'console mode'
}
// *add 0.9.4 support for extern "C". Returns int because we may need to be explicit.
bool in_extern()
{ return state.extern_flag; }
bool in_extern_C()
{ return state.extern_flag_C; }
// parser state management
void ParserState::reset()
{
in_match = false;
was_fun_ptr = false;
in_declaration = false;
in_typedef = false;
in_class = false;
in_method = false;
in_switch = false;
class_dcl = t_void;
scope_context = NULL;
in_loop = false;
in_construct_destruct = IsPlain;
extern_flag = false;
extern_flag_C = false;
modifier = None;
err = "";
arg_list.clear();
// NB to restore any stacks!
// note this mucks up the state while we are paused...need
// to think this one through HACK04
if (!Engine::paused()) {
context_stack.clear();
push_context(&global());
}
// mCodeBlock.pstart = code().end_code(); // will clear static code buffer
if (is_function_code()) {
code().end_code(); // clear the function code buffer
set_function_code(false); // so we're back in static code
}
block_stack.clear(); // clear any pending blocks
tstack.clear(); // clear the type stack
IEF=false;
s_expr_handler = NULL;
dcl_init_list.clear();
}
void ParserState::push_context(Table *tbl)
{
context_stack.push(tbl);
}
Table& ParserState::context()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -