diff --git a/sp/src/vscript/sqdbg/sqdbg/debug.h b/sp/src/vscript/sqdbg/sqdbg/debug.h index e7d04b9c..90cb1ea8 100644 --- a/sp/src/vscript/sqdbg/sqdbg/debug.h +++ b/sp/src/vscript/sqdbg/sqdbg/debug.h @@ -106,6 +106,7 @@ } while(0) #endif #define Verify( x ) Assert(x) + #define STATIC_ASSERT( x ) static_assert( x, #x ) #else #define DebuggerBreak() ((void)0) #define Assert( x ) ((void)0) @@ -113,12 +114,15 @@ #define AssertMsg1( x, msg, a1 ) ((void)0) #define AssertMsg2( x, msg, a1, a2 ) ((void)0) #define Verify( x ) x + #define STATIC_ASSERT( x ) #endif // _DEBUG #endif #include +#define STATIC_ASSERT COMPILE_TIME_ASSERT + // Misdefined for GCC in platform.h #undef UNREACHABLE diff --git a/sp/src/vscript/sqdbg/sqdbg/json.h b/sp/src/vscript/sqdbg/sqdbg/json.h index d42a5365..1a199691 100644 --- a/sp/src/vscript/sqdbg/sqdbg/json.h +++ b/sp/src/vscript/sqdbg/sqdbg/json.h @@ -275,9 +275,13 @@ static inline void PutStr( CBuffer *buffer, const string_t &str ) #ifdef SQDBG_VALIDATE_SENT_MSG for ( unsigned int i = 0; i < str.len; i++ ) { - AssertMsg( IN_RANGE_CHAR( str.ptr[i], 0x20, 0x7E ) && - ( ( str.ptr[i] != '\\' && str.ptr[i] != '\"' ) || ( i && str.ptr[i-1] == '\\' ) ), - "control char in json string" ); + if ( str.ptr[i] == '\\' && ( str.ptr[i+1] == '\\' || str.ptr[i+1] == '\"' ) ) + { + i++; + continue; + } + + AssertMsg( str.ptr[i] != '\\' && IN_RANGE_CHAR( str.ptr[i], 0x20, 0x7E ), "control char in json string" ); } #endif } @@ -433,7 +437,7 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote ) idx += printhex< true, false >( mem + idx, buffer->Capacity() - idx, - (SQChar)*(unsigned char*)c ); + (SQUnsignedChar)*(unsigned char*)c ); } } } @@ -503,6 +507,7 @@ static inline void PutInt( CBuffer *buffer, I val ) template < bool padding, typename I > static inline void PutHex( CBuffer *buffer, I val ) { + STATIC_ASSERT( IS_UNSIGNED( I ) ); buffer->base.Ensure( buffer->Size() + countdigits<16>( val ) + 1 ); int len = printhex< padding >( buffer->Base() + buffer->Size(), buffer->Capacity() - buffer->Size(), val ); buffer->size += len; @@ -699,7 +704,7 @@ public: } else { - PutHex< false >( m_pBuffer, val ); + PutHex< false >( m_pBuffer, cast_unsigned( I, val ) ); } PutChar( m_pBuffer, ']' ); PutChar( m_pBuffer, '\"' ); @@ -850,7 +855,7 @@ private: else { buf = m_Allocator->Alloc(5); - int i = printhex< true, true, false >( buf, 5, token ); + int i = printhex< true, true, false >( buf, 5, (unsigned char)token ); Assert( i == 4 ); buf[i] = 0; } @@ -877,6 +882,24 @@ private: m_error[len] = 0; } + bool IsValue( char token ) + { + switch ( token ) + { + case Token_String: + case Token_Integer: + case Token_Float: + case Token_False: + case Token_True: + case Token_Null: + case Token_Table: + case Token_Array: + return true; + default: + return false; + } + } + char NextToken( string_t &token ) { while ( m_cur < m_end ) @@ -1206,7 +1229,7 @@ err_eof: type = NextToken( token ); type = ParseValue( type, token, &kv->val ); - if ( type == Token_Error ) + if ( !IsValue( type ) ) { SetError( "invalid token %s @ %i", Char(type), Index() ); return Token_Error; @@ -1239,7 +1262,7 @@ err_eof: for (;;) { - if ( type == Token_Error ) + if ( !IsValue( type ) ) { SetError( "expected '%c', got %s @ %i", ']', Char(type), Index() ); return Token_Error; @@ -1315,7 +1338,7 @@ err_eof: value->type = JSON_NULL; return type; default: - return type; + return Token_Error; } } }; diff --git a/sp/src/vscript/sqdbg/sqdbg/net.h b/sp/src/vscript/sqdbg/sqdbg/net.h index 34f5f407..f228aa7a 100644 --- a/sp/src/vscript/sqdbg/sqdbg/net.h +++ b/sp/src/vscript/sqdbg/sqdbg/net.h @@ -842,7 +842,7 @@ public: m_pRecvBufPtr( m_pRecvBuf ), m_bWSAInit( false ) { - Assert( sizeof(m_pRecvBuf) <= ( 1 << ( sizeof(CMessagePool::message_t::len) * 8 ) ) ); + STATIC_ASSERT( sizeof(m_pRecvBuf) <= ( 1 << ( sizeof(CMessagePool::message_t::len) * 8 ) ) ); } }; diff --git a/sp/src/vscript/sqdbg/sqdbg/server.cpp b/sp/src/vscript/sqdbg/sqdbg/server.cpp index 899796e9..89d3bae4 100644 --- a/sp/src/vscript/sqdbg/sqdbg/server.cpp +++ b/sp/src/vscript/sqdbg/sqdbg/server.cpp @@ -5,7 +5,7 @@ // Squirrel Debugger // -#define SQDBG_SV_VER 5 +#define SQDBG_SV_VER 6 #include "sqdbg.h" @@ -116,6 +116,7 @@ void sqdbg_sleep( int ms ) #define memzero(p) memset( (char*)(p), 0, sizeof(*(p)) ) #define ALIGN(v, a) (((v) + ((a)-1)) & ~((a)-1)) +#define ROUND(v, a) ((v) + (a) - (v) % (a)) #ifndef _WIN32 #undef offsetof @@ -137,14 +138,24 @@ void sqdbg_sleep( int ms ) #define _SC(s) s #endif -#if defined(SQUNICODE) && !defined(WCHAR_SIZE) -#ifdef _WIN32 - #define WCHAR_SIZE 2 +#ifdef SQUNICODE + #ifdef _WIN32 + #ifndef WCHAR_SIZE + #define WCHAR_SIZE 2 + #endif + typedef uint16_t SQUnsignedChar; + #else + #ifndef WCHAR_SIZE + #define WCHAR_SIZE 4 + #endif + typedef uint32_t SQUnsignedChar; + #endif #else - #define WCHAR_SIZE 4 -#endif + typedef unsigned char SQUnsignedChar; #endif +STATIC_ASSERT( sizeof(SQChar) == sizeof(SQUnsignedChar) ); + #ifndef scstrlen #ifdef SQUNICODE #define scstrlen wcslen @@ -272,10 +283,14 @@ void sqdbg_sleep( int ms ) #define SUPPORTS_DEREF_OP #if SQUIRREL_VERSION_NUMBER >= 300 - #define CHAINABLE_FUNCPROTO + #define ACCESSIBLE_FUNCPROTO #endif #endif +#if defined(SQDBG_SUPPORTS_FUNCPROTO_LIST) && !defined(ACCESSIBLE_FUNCPROTO) + #define ACCESSIBLE_FUNCPROTO +#endif + #include "str.h" #include "json.h" #include "protocol.h" @@ -641,12 +656,9 @@ public: Assert( vm->_top == top ); } }; +#define STACKCHECK( vm ) CStackCheck stackcheck( vm ) #else -class CStackCheck -{ -public: - CStackCheck( HSQUIRRELVM ) {} -}; +#define STACKCHECK( vm ) (void)0 #endif @@ -659,7 +671,6 @@ public: typedef unsigned int hgroup_t; static const hnode_t INVALID_HANDLE = (hnode_t)-1; -#pragma pack(push, 4) struct node_t { void *func; @@ -669,7 +680,6 @@ public: sample_t sampleStart; hnode_t id; }; -#pragma pack(pop) struct nodetag_t { @@ -1118,7 +1128,7 @@ public: if ( tag ) { return STRLEN(PROF_GROUP_OUTPUT_TEMPLATE) + - ALIGN( tag->_len, PROF_GROUP_NAME_LEN_ALIGNMENT ) + + ROUND( tag->_len, PROF_GROUP_NAME_LEN_ALIGNMENT ) + 1; } @@ -1203,7 +1213,7 @@ public: memcpy( buf, group->tag->_val, sq_rsl(len) ); buf += len; size -= len; - for ( int i = ALIGN( len, PROF_GROUP_NAME_LEN_ALIGNMENT ) - len; i-- > 0; ) + for ( int i = ROUND( len, PROF_GROUP_NAME_LEN_ALIGNMENT ) - len; i-- > 0; ) { *buf++ = ' '; size--; @@ -1972,6 +1982,9 @@ typedef enum VARREF_INSTRUCTIONS, VARREF_OUTERS, VARREF_LITERALS, +#ifdef SQDBG_SUPPORTS_FUNCPROTO_LIST + VARREF_FUNCTIONS, +#endif VARREF_METAMETHODS, VARREF_ATTRIBUTES, VARREF_CALLSTACK, @@ -1993,6 +2006,9 @@ inline bool IsObjectRef( EVARREF type ) type == VARREF_INSTRUCTIONS || type == VARREF_OUTERS || type == VARREF_LITERALS || +#ifdef SQDBG_SUPPORTS_FUNCPROTO_LIST + type == VARREF_FUNCTIONS || +#endif type == VARREF_METAMETHODS || type == VARREF_ATTRIBUTES || type == VARREF_CALLSTACK ); @@ -2079,6 +2095,9 @@ struct objref_t DELEGABLE_META, CUSTOMMEMBER, STACK, +#ifdef SQDBG_SUPPORTS_FUNCPROTO_LIST + FUNCPROTO, +#endif INT, VIRTUAL_REF, VIRTUAL_SIZE, @@ -3022,7 +3041,7 @@ void SQDebugServer::Attach( HSQUIRRELVM vm ) sq_addref( m_pRootVM, &m_EnvGetVal ); { - CStackCheck stackcheck( m_pRootVM ); + STACKCHECK( m_pRootVM ); SQObjectPtr ref; sqdbg_get_debugger_ref( m_pRootVM, ref ); @@ -3700,12 +3719,12 @@ void SQDebugServer::ProcessRequest( const json_table_t &table, int seq ) ProfSwitchThread( m_pCurVM ); #endif - OnRequest_RestartFrame( *arguments, seq ); - RestoreCachedInstructions(); ClearCachedInstructions(); RemoveReturnValues(); + + OnRequest_RestartFrame( *arguments, seq ); } #endif else if ( command.IsEqualTo( "gotoTargets" ) ) @@ -3735,12 +3754,12 @@ void SQDebugServer::ProcessRequest( const json_table_t &table, int seq ) ProfSwitchThread( m_pCurVM ); #endif - OnRequest_Goto( *arguments, seq ); - RestoreCachedInstructions(); ClearCachedInstructions(); RemoveReturnValues(); + + OnRequest_Goto( *arguments, seq ); } else if ( command.IsEqualTo( "next" ) ) { @@ -4227,7 +4246,7 @@ void SQDebugServer::OnRequest_SetFunctionBreakpoints( const json_table_t &argume int line = 0; // function source: funcname,filename:line - for ( int j = name.len - 1; j > 1; j-- ) + for ( int j = name.len - 1; j >= 0; j-- ) { if ( !line && name.ptr[j] == ':' ) { @@ -5341,7 +5360,7 @@ static void Escape( char *dst, unsigned int *len, unsigned int size ) break; } - SQChar val = (SQChar)((unsigned char*)dst)[0]; + SQUnsignedChar val = (SQUnsignedChar)((unsigned char*)dst)[0]; _memmove( dst + 2 + sizeof(SQChar) * 2, dst + 1, @@ -5699,21 +5718,21 @@ getfloat: char *buf = ScratchPad( size ); int len; - if ( _integer(obj) > (SQInteger)( 1 << ( ( sizeof(SQChar) << 3 ) - 1 ) ) ) + // Allow both signed and unsigned char values ( -1 == 255, -128 == 128, -127 == 129 ) + if ( _integer(obj) > + (SQInteger)( (SQUnsignedChar)-1 >> (int)( sizeof(SQChar) >= sizeof(SQInteger) ) ) || + _integer(obj) < + (SQInteger)-( ( (SQUnsignedChar)-1 >> 1 ) + 1 ) ) { len = printint( buf, size, _integer(obj) ); return { buf, (unsigned int)len }; } - SQChar ch = (SQChar)_integer(obj); + SQUnsignedChar ch = (SQUnsignedChar)_integer(obj); if ( !( flags & kFS_Hexadecimal ) ) { -#ifdef SQUNICODE - len = printint( buf, size, ch ); -#else - len = printint( buf, size, (unsigned char)ch ); -#endif + len = printint( buf, size, (SQUnsignedInteger)ch ); } else { @@ -5734,9 +5753,9 @@ getfloat: buf[len++] = (char)ch; } #ifdef SQUNICODE - else if ( IsValidUnicode( &ch, 1 ) ) + else if ( IsValidUnicode( (SQChar*)&ch, 1 ) ) { - len += SQUnicodeToUTF8( buf + len, size - len - 1, &ch, 1 ); + len += SQUnicodeToUTF8( buf + len, size - len - 1, (SQChar*)&ch, 1 ); } #endif else @@ -5745,7 +5764,7 @@ getfloat: buf[len++] = 'x'; #ifdef SQUNICODE - if ( ch <= (SQChar)0xFF ) + if ( ch <= 0xFF ) { len += printhex< true, false, false >( buf + len, size, (unsigned char)ch ); } @@ -5945,7 +5964,7 @@ getfloat: } else { - buf.PutHex( _table(obj)->CountUsed(), false ); + buf.PutHex( (SQUnsignedInteger)_table(obj)->CountUsed(), false ); } buf.Put('}'); @@ -6056,6 +6075,9 @@ getfloat: } case OT_CLOSURE: case OT_NATIVECLOSURE: +#ifdef ACCESSIBLE_FUNCPROTO + case OT_FUNCPROTO: +#endif { const SQObjectPtr *name; @@ -6063,10 +6085,17 @@ getfloat: { name = &_fp(_closure(obj)->_function)->_name; } - else + else if ( sq_type(obj) == OT_NATIVECLOSURE ) { name = &_nativeclosure(obj)->_name; } +#ifdef ACCESSIBLE_FUNCPROTO + else if ( sq_type(obj) == OT_FUNCPROTO ) + { + name = &_funcproto(obj)->_name; + } +#endif + else UNREACHABLE(); if ( sq_type(*name) == OT_STRING ) { @@ -6195,7 +6224,7 @@ SQString *SQDebugServer::GetLocalVarName( const SQFunctionProto *func, const SQI const SQLocalVarInfo &var = func->_localvarinfos[i]; if ( (unsigned int)var._pos == pos && - var._start_op <= ip + s_nTargetAssignment && var._end_op + 1 >= ip ) + var._start_op <= ip + s_nTargetAssignment && var._end_op >= ip ) { return sq_type(var._name) == OT_STRING ? _string(var._name) : NULL; } @@ -6235,12 +6264,48 @@ void SQDebugServer::PrintOuter( const SQFunctionProto *func, int pos, stringbufe void SQDebugServer::PrintLiteral( const SQFunctionProto *func, int pos, stringbufext_t &buf ) { - string_t val = GetValue( func->_literals[pos] ); + const SQObjectPtr &val = func->_literals[pos]; - if ( val.len > 64 ) - val.len = 64; + switch ( sq_type(val) ) + { + case OT_INTEGER: + case OT_FLOAT: + case OT_BOOL: + case OT_NULL: + case OT_STRING: + { + string_t str = GetValue( val ); - buf.Puts( val ); + if ( str.len > 64 ) + str.len = 64; + + buf.Puts( str ); + break; + } + case OT_CLASS: + case OT_INSTANCE: + { + const classdef_t *def = + FindClassDef( sq_type(val) == OT_CLASS ? _class(val) : _instance(val)->_class ); + + if ( def && def->name.ptr ) + { + buf.Puts( GetType( val ) ); + buf.Put( ' ' ); + + string_t str; + str.Assign( def->name.ptr + FMT_PTR_LEN + 1, def->name.len - FMT_PTR_LEN - 1 ); + + if ( str.len > 64 - 9 ) + str.len = 64 - 9; + + buf.Puts( str ); + break; + } + } + default: + buf.Puts( GetType( val ) ); + } } void SQDebugServer::PrintStackTarget( const SQFunctionProto *func, const SQInstruction *instr, @@ -6287,9 +6352,19 @@ void SQDebugServer::DescribeInstruction( const SQInstruction *instr, const SQFun { case _OP_LOADNULLS: { - PrintStackVar( func, instr, instr->_arg0, buf ); - buf.Put( ' ' ); - buf.PutInt( instr->_arg1 ); + if ( instr->_arg1 == 1 ) + { + PrintStackVar( func, instr, instr->_arg0, buf ); + } + else + { + buf.Put( '[' ); + buf.PutInt( (int)instr->_arg0 ); + buf.Put( ']' ); + buf.Put( ' ' ); + buf.PutInt( instr->_arg1 ); + } + break; } case _OP_LOADINT: @@ -7849,6 +7924,13 @@ bool SQDebugServer::Get( const objref_t &obj, SQObjectPtr &value ) return false; } +#ifdef SQDBG_SUPPORTS_FUNCPROTO_LIST + case objref_t::FUNCPROTO: + { + value = *obj.ptr; + return true; + } +#endif case objref_t::INT: { value = (SQInteger)obj.val; @@ -8036,6 +8118,23 @@ bool SQDebugServer::Set( const objref_t &obj, const SQObjectPtr &value ) return false; } +#ifdef SQDBG_SUPPORTS_FUNCPROTO_LIST + case objref_t::FUNCPROTO: + { + if ( sq_type(value) == OT_FUNCPROTO ) + { + *obj.ptr = value; + return true; + } + else if ( sq_type(value) == OT_CLOSURE ) + { + *obj.ptr = _closure(value)->_function; + return true; + } + + return false; + } +#endif default: UNREACHABLE(); } } @@ -8396,9 +8495,6 @@ public: int opbufidx = -1; int unaryidx = -1; - // Recursively parsing unary operators adds the complexity - // of keeping track of and reverting to the previous token - // Using an operator stack is simpler but limits the amount unsigned char unarybuf[ SQDBG_COMPILER_MAX_UNARY_STACK ]; unsigned char opbuf[2]; char deleteop = 0; @@ -10486,7 +10582,7 @@ private: { if ( ISREFCOUNTED( sq_type(val) ) && sq_type(val) != OT_STRING ) { - val = (SQInteger)_refcounted(val); + val = (SQInteger)(uintptr_t)_refcounted(val); return true; } else if ( sq_type(val) == OT_NULL ) @@ -11189,6 +11285,7 @@ private: token._string.IsEqualTo("throw") || token._string.IsEqualTo("static") || token._string.IsEqualTo("return") || + token._string.IsEqualTo("resume") || token._string.IsEqualTo("foreach") || token._string.IsEqualTo("function") ) { @@ -12099,11 +12196,8 @@ bool SQDebugServer::GetObj_Var( const SQObjectPtr &var, const SQObjectPtr &key, _integer(key) >= 0 && _integer(key) < _string(var)->_len ) { out.type = (objref_t::EOBJREF)( objref_t::INT | objref_t::READONLY ); -#ifdef SQUNICODE + // Sign will be extended out.val = (int)_string(var)->_val[ _integer(key) ]; -#else - out.val = (int)(unsigned char)_string(var)->_val[ _integer(key) ]; -#endif value = (SQInteger)out.val; return true; } @@ -12625,11 +12719,13 @@ bool SQDebugServer::GetObj_VarRef( const varref_t *ref, string_t &expression, ob } case VARREF_OUTERS: { - AssertClient( sq_type(ref->GetVar()) == OT_CLOSURE ); + SQObject target = ref->GetVar(); - if ( sq_type(ref->GetVar()) == OT_CLOSURE ) + AssertClient( sq_type(target) == OT_CLOSURE ); + + if ( sq_type(target) == OT_CLOSURE ) { - SQClosure *pClosure = _closure(ref->GetVar()); + SQClosure *pClosure = _closure(target); SQFunctionProto *func = _fp(pClosure->_function); for ( int i = 0; i < func->_noutervalues; i++ ) @@ -12649,16 +12745,18 @@ bool SQDebugServer::GetObj_VarRef( const varref_t *ref, string_t &expression, ob } case VARREF_LITERALS: { - AssertClient( sq_type(ref->GetVar()) == OT_CLOSURE ); + SQObject target = ref->GetVar(); - if ( sq_type(ref->GetVar()) == OT_CLOSURE ) + AssertClient( sq_type(target) == OT_FUNCPROTO ); + + if ( sq_type(target) == OT_FUNCPROTO ) { int idx; if ( atoi( expression, &idx ) && - idx >= 0 && idx < (int)_fp(_closure(ref->GetVar())->_function)->_nliterals ) + idx >= 0 && idx < (int)_funcproto(target)->_nliterals ) { out.type = objref_t::PTR; - out.ptr = &_fp(_closure(ref->GetVar())->_function)->_literals[idx]; + out.ptr = &_funcproto(target)->_literals[idx]; value = *out.ptr; return true; } @@ -12666,6 +12764,29 @@ bool SQDebugServer::GetObj_VarRef( const varref_t *ref, string_t &expression, ob return false; } +#ifdef SQDBG_SUPPORTS_FUNCPROTO_LIST + case VARREF_FUNCTIONS: + { + SQObject target = ref->GetVar(); + + AssertClient( sq_type(target) == OT_FUNCPROTO ); + + if ( sq_type(target) == OT_FUNCPROTO ) + { + int idx; + if ( atoi( expression, &idx ) && + idx >= 0 && idx < (int)_funcproto(target)->_nfunctions ) + { + out.type = objref_t::FUNCPROTO; + out.ptr = &_funcproto(target)->_functions[idx]; + value = *out.ptr; + return true; + } + } + + return false; + } +#endif case VARREF_METAMETHODS: { int mm = -1; @@ -12711,28 +12832,44 @@ bool SQDebugServer::GetObj_VarRef( const varref_t *ref, string_t &expression, ob } case VARREF_STACK: { - AssertClient( expression.len > 2 ); + AssertClient( expression.len > 5 ); - if ( expression.len <= 2 ) + if ( expression.len <= 5 ) return false; - while ( expression.len > 3 && expression.ptr[expression.len-1] != ']' ) + while ( expression.len > 5 && expression.ptr[expression.len-1] != ']' ) expression.len--; expression.ptr++; expression.len -= 2; - int idx; - if ( strtoint( expression, &idx ) && - idx >= 0 && idx < (int)ref->GetThread()->_stack.size() ) - { - out.type = objref_t::PTR; - out.ptr = &ref->GetThread()->_stack._vals[idx]; - value = *out.ptr; - return true; - } + AssertClient( expression.ptr[-1] == '[' ); + char *pIdx = strchr( expression.ptr, ']' ); + string_t strFrame( expression.ptr, pIdx - expression.ptr ); - return false; + HSQUIRRELVM vm = ref->GetThread(); + + int frame; + if ( !pIdx || !strtoint( strFrame, &frame ) || + frame < 0 || frame >= (int)vm->_callsstacksize ) + return false; + + int stackbase = GetStackBase( vm, frame ); + + expression.ptr += strFrame.len + 2; + expression.len -= strFrame.len + 2; + + AssertClient( expression.ptr[-1] == '[' ); + + int idx; + if ( !strtoint( expression, &idx ) || + stackbase + idx < 0 || stackbase + idx >= (int)vm->_stack.size() ) + return false; + + out.type = objref_t::PTR; + out.ptr = &vm->_stack._vals[ stackbase + idx ]; + value = *out.ptr; + return true; } case VARREF_INSTRUCTIONS: case VARREF_CALLSTACK: @@ -13609,7 +13746,7 @@ void SQDebugServer::FillCompletions( const SQObjectPtr &target, HSQUIRRELVM vm, if ( def && sq_type(def->metamembers) != OT_NULL && - _instance(target)->GetMetaMethod( vm, MT_GET, mm ) ) + _instance(env)->GetMetaMethod( vm, MT_GET, mm ) ) { for ( unsigned int i = 0; i < _array(def->metamembers)->_values.size(); i++ ) { @@ -14938,12 +15075,11 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq break; } case OT_CLOSURE: -#ifdef CHAINABLE_FUNCPROTO - // Only reachable through compiler address deref +#ifdef ACCESSIBLE_FUNCPROTO case OT_FUNCPROTO: #endif { -#ifdef CHAINABLE_FUNCPROTO +#ifdef ACCESSIBLE_FUNCPROTO SQFunctionProto *func = ( sq_type(target) == OT_CLOSURE ) ? _fp(_closure(target)->_function) : _funcproto(target); @@ -15026,7 +15162,7 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq } else { - buf.PutHex( nparams, false ); + buf.PutHex( (unsigned int)nparams, false ); } buf.Puts("..."); @@ -15071,18 +15207,36 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq SetVirtualHint( elem ); } -#ifdef CHAINABLE_FUNCPROTO +#ifdef SQDBG_SUPPORTS_FUNCPROTO_LIST + if ( func->_nfunctions ) + { + wjson_table_t elem = variables.AppendTable(); + elem.SetString( "name", INTERNAL_TAG("functions") ); + elem.SetString( "value", GetValue( func->_nfunctions, flags ) ); + elem.SetInt( "variablesReference", ToVarRef( VARREF_FUNCTIONS, ToSQObject( func ) ) ); + SetVirtualHint( elem ); + } +#endif + + if ( func->_noutervalues ) + { + wjson_table_t elem = variables.AppendTable(); + elem.SetString( "name", INTERNAL_TAG("outervalues") ); + elem.SetString( "value", GetValue( func->_noutervalues, flags ) ); +#ifdef ACCESSIBLE_FUNCPROTO + int v = ( sq_type(target) == OT_CLOSURE ) ? ToVarRef( VARREF_OUTERS, target ) : -1; + elem.SetInt( "variablesReference", v ); +#else + Assert( sq_type(target) == OT_CLOSURE ); + elem.SetInt( "variablesReference", ToVarRef( VARREF_OUTERS, target ) ); +#endif + SetVirtualHint( elem ); + } + +#ifdef ACCESSIBLE_FUNCPROTO if ( sq_type(target) == OT_CLOSURE ) #endif { - if ( func->_noutervalues ) - { - wjson_table_t elem = variables.AppendTable(); - elem.SetString( "name", INTERNAL_TAG("outervalues") ); - elem.SetString( "value", GetValue( func->_noutervalues, flags ) ); - elem.SetInt( "variablesReference", ToVarRef( VARREF_OUTERS, target ) ); - SetVirtualHint( elem ); - } #ifdef CLOSURE_ENV_ISVALID if ( CLOSURE_ENV_ISVALID( _closure(target)->_env ) ) { @@ -15140,7 +15294,7 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq } else { - buf.PutHex( nparams < 0 ? -nparams : nparams, false ); + buf.PutHex( (unsigned int)( nparams < 0 ? -nparams : nparams ), false ); } if ( nparams < 0 ) @@ -15486,6 +15640,40 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq break; } +#ifdef SQDBG_SUPPORTS_FUNCPROTO_LIST + case VARREF_FUNCTIONS: + { + SQObject target = ref->GetVar(); + + if ( sq_type(target) != OT_FUNCPROTO ) + { + DAP_ERROR_RESPONSE( seq, "variables" ); + DAP_ERROR_BODY( 0, "invalid object" ); + DAP_SEND(); + return; + } + + SQFunctionProto *func = _funcproto(target); + + DAP_START_RESPONSE( seq, "variables" ); + DAP_SET_TABLE( body ); + wjson_array_t variables = body.SetArray( "variables" ); + + for ( int i = 0; i < func->_nfunctions; i++ ) + { + const SQObjectPtr &val = func->_functions[i]; + + wjson_table_t elem = variables.AppendTable(); + elem.SetIntString( "name", i ); + JSONSetString( elem, "value", val, flags ); + elem.SetString( "type", GetType( val ) ); + elem.SetInt( "variablesReference", ToVarRef( val ) ); + } + DAP_SEND(); + + break; + } +#endif case VARREF_METAMETHODS: { SQObject target = ref->GetVar(); @@ -15673,69 +15861,107 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq DAP_SET_TABLE( body ); wjson_array_t variables = body.SetArray( "variables" ); - int stackbase = -1; - int callframe = 0; + int stackbase = 0; + int callframe = -1; + int next = vm->_callsstacksize ? vm->_callsstack[0]._prevstkbase : 0; + int idx = 0; + const int max = vm->_stack.size(); - if ( vm->_callsstacksize ) - stackbase = vm->_callsstack[callframe]._prevstkbase; - - for ( int i = 0; i < (int)vm->_stack.size(); i++ ) + for (;;) { - const SQObjectPtr &val = vm->_stack._vals[i]; + callframe++; - if ( i > vm->_top && sq_type(val) == OT_NULL ) - continue; - - wjson_table_t elem = variables.AppendTable(); + if ( callframe < vm->_callsstacksize ) { - jstringbuf_t name = elem.SetStringAsBuf( "name" ); - name.Put('['); + stackbase = next; - if ( !( flags & kFS_Hexadecimal ) ) + if ( callframe + 1 < vm->_callsstacksize ) { - name.PutInt( i ); + next = stackbase + vm->_callsstack[ callframe + 1 ]._prevstkbase; } else { - name.PutHex( i, false ); - } - - name.Put(']'); - - if ( stackbase == i ) - { - name.Put('*'); - - if ( callframe == frame ) - { - name.Put('~'); - } -#ifndef NATIVE_DEBUG_HOOK - else if ( m_State == ThreadState_Suspended && - callframe == vm->_callsstacksize - 1 ) - { - if ( sq_type(vm->_callsstack[callframe]._closure) == OT_NATIVECLOSURE && - _nativeclosure(vm->_callsstack[callframe]._closure)->_function == - &SQDebugServer::SQDebugHook ) - { - name.Put('d'); - } - } -#endif - - if ( ++callframe < vm->_callsstacksize ) - stackbase += vm->_callsstack[callframe]._prevstkbase; - } - else if ( vm->_top == i ) - { - name.Put('_'); + next = max; } } - JSONSetString( elem, "value", val, flags ); - elem.SetString( "type", GetType( val ) ); - elem.SetInt( "variablesReference", ToVarRef( val ) ); - if ( ShouldPageArray( val, 16 * ARRAY_PAGE_LIMIT ) ) - elem.SetInt( "indexedVariables", (int)_array(val)->_values.size() ); + else + { + if ( callframe ) + callframe--; + + next = max; + } + + for ( ; idx < next; idx++ ) + { + const SQObjectPtr &val = vm->_stack._vals[idx]; + + if ( idx > vm->_top && sq_type(val) == OT_NULL ) + continue; + + wjson_table_t elem = variables.AppendTable(); + { + jstringbuf_t name = elem.SetStringAsBuf( "name" ); + name.Put('['); + + if ( !( flags & kFS_Hexadecimal ) ) + { + name.PutInt( callframe ); + } + else + { + name.PutHex( (unsigned int)callframe, false ); + } + + name.Put(']'); + name.Put('['); + + if ( !( flags & kFS_Hexadecimal ) ) + { + name.PutInt( idx - stackbase ); + } + else + { + name.PutHex( (unsigned int)( idx - stackbase ), false ); + } + + name.Put(']'); + + if ( idx == stackbase ) + { + name.Put('*'); + + if ( callframe == frame ) + { + name.Put('~'); + } +#ifndef NATIVE_DEBUG_HOOK + else if ( m_State == ThreadState_Suspended && + callframe == vm->_callsstacksize - 1 ) + { + if ( sq_type(vm->_callsstack[callframe]._closure) == OT_NATIVECLOSURE && + _nativeclosure(vm->_callsstack[callframe]._closure)->_function == + &SQDebugServer::SQDebugHook ) + { + name.Put('d'); + } + } +#endif + } + else if ( vm->_top == idx ) + { + name.Put('_'); + } + } + JSONSetString( elem, "value", val, flags ); + elem.SetString( "type", GetType( val ) ); + elem.SetInt( "variablesReference", ToVarRef( val ) ); + if ( ShouldPageArray( val, 16 * ARRAY_PAGE_LIMIT ) ) + elem.SetInt( "indexedVariables", (int)_array(val)->_values.size() ); + } + + if ( next == max ) + break; } DAP_SEND(); @@ -15865,7 +16091,7 @@ void SQDebugServer::OnRequest_SetVariable( const json_table_t &arguments, int se DAP_ERROR_BODY( 0, "could not set '{name}'" ); error.SetBool( "showUser", true ); wjson_table_t variables = error.SetTable( "variables" ); - JSONSetString( variables, "name", obj.key ); + variables.SetString( "name", strName ); DAP_SEND(); return; } @@ -16342,7 +16568,7 @@ void SQDebugServer::OnRequest_Disassemble( const json_table_t &arguments, int se #ifdef SUPPORTS_RESTART_FRAME void SQDebugServer::OnRequest_RestartFrame( const json_table_t &arguments, int seq ) { - Assert( m_State == ThreadState_Suspended ); + AssertClient( m_State != ThreadState_Running ); HSQUIRRELVM vm; int frame; @@ -16846,7 +17072,7 @@ bool SQDebugServer::InstructionStep( HSQUIRRELVM vm, SQVM::CallInfo *ci, int ins SQInstruction *instrEnd = func->_instructions + func->_ninstructions; SQInstruction *ip = ci->_ip - instrOffset; - Assert( ip >= func->_instructions && ip < instrEnd ); + Assert( ip >= func->_instructions ); { for (;;) @@ -16973,7 +17199,7 @@ bool SQDebugServer::Step( HSQUIRRELVM vm, SQVM::CallInfo *ci ) ClearCachedInstructions(); SQFunctionProto *func = _fp(_closure(ci->_closure)->_function); - Assert( ci->_ip >= func->_instructions && ci->_ip < func->_instructions + func->_ninstructions ); + Assert( ci->_ip >= func->_instructions ); // Check if this function was compiled with debug info // The first op is going to be a line op @@ -17000,7 +17226,7 @@ bool SQDebugServer::Step( HSQUIRRELVM vm, SQVM::CallInfo *ci ) _CacheInstruction( func, func->_instructions + op ); // Set break point at every possible jump target - for ( SQInstruction *ip = ci->_ip + 1; ip <= func->_instructions + op; ip++ ) + for ( SQInstruction *ip = ci->_ip; ip <= func->_instructions + op; ip++ ) { if ( IsJumpOp( ip ) && GetJumpCount( ip ) != 0 ) { @@ -17040,6 +17266,14 @@ void SQDebugServer::CacheInstruction( SQInstruction *instr ) void SQDebugServer::ClearCachedInstructions() { +#ifdef SQDBG_WEAK_INSTRUCTION_REF + for ( int i = m_CachedInstructions.Size(); i--; ) + { + cachedinstr_t &cached = m_CachedInstructions[i]; + __ObjRelease( cached.func ); + } +#endif + m_CachedInstructions.Clear(); } @@ -17050,10 +17284,7 @@ void SQDebugServer::RestoreCachedInstructions() cachedinstr_t &cached = m_CachedInstructions[i]; #ifdef SQDBG_WEAK_INSTRUCTION_REF if ( cached.func && sq_type(cached.func->_obj) == OT_FUNCPROTO ) - { _funcproto(cached.func->_obj)->_instructions[ cached.index ] = cached.instr; - __ObjRelease( cached.func ); - } #else if ( cached.ip ) *cached.ip = cached.instr; @@ -17068,10 +17299,7 @@ void SQDebugServer::UndoRestoreCachedInstructions() cachedinstr_t &cached = m_CachedInstructions[i]; #ifdef SQDBG_WEAK_INSTRUCTION_REF if ( cached.func && sq_type(cached.func->_obj) == OT_FUNCPROTO ) - { memzero( &_funcproto(cached.func->_obj)->_instructions[ cached.index ] ); - __ObjAddRef( cached.func ); - } #else if ( cached.ip ) memzero( cached.ip ); @@ -17337,7 +17565,15 @@ int SQDebugServer::AddFunctionBreakpoint( const string_t &func, const string_t & SQChar *pSrc = pFunc + funcsize; sqstring_t wfunc, wsrc; - wfunc.Assign( pFunc, UTF8ToSQUnicode( pFunc, funcsize, func.ptr, func.len ) ); + + if ( func.IsEmpty() ) + { + wfunc.Assign( _SC("") ); + } + else + { + wfunc.Assign( pFunc, UTF8ToSQUnicode( pFunc, funcsize, func.ptr, func.len ) ); + } if ( funcsrc.IsEmpty() ) { @@ -17828,6 +18064,10 @@ sqstring_t SQDebugServer::PrintDisassembly( SQClosure *target, SQChar *scratch, int idx; if ( func->_ndefaultparams && ( idx = (int)func->_ndefaultparams - ( nparams - i ) ) >= 0 ) { + len = STRLEN(" = "); + memcpy( buf, _SC(" = "), sq_rsl(len) ); + buf += len; + const SQObjectPtr &val = target->_defaultparams[idx]; string_t str; @@ -17838,19 +18078,39 @@ sqstring_t SQDebugServer::PrintDisassembly( SQClosure *target, SQChar *scratch, case OT_BOOL: case OT_NULL: case OT_STRING: - str = GetValue( val, kFS_NoAddr ); + str = GetValue( val ); + len = min( str.len, DISASM_MAX_PARAM_NAME_LEN - 3 ); break; + case OT_CLASS: + case OT_INSTANCE: + { + const classdef_t *def = + FindClassDef( sq_type(val) == OT_CLASS ? _class(val) : _instance(val)->_class ); + + if ( def && def->name.ptr ) + { + str = GetType( val ); + len = min( (int)str.len, DISASM_MAX_PARAM_NAME_LEN - 4 ); +#ifdef SQUNICODE + UTF8ToSQUnicode( buf, _bs, str.ptr, len ); +#else + memcpy( buf, str.ptr, sq_rsl(len) ); +#endif + buf += len; + *buf++ = ' '; + + str.Assign( def->name.ptr + FMT_PTR_LEN + 1, def->name.len - FMT_PTR_LEN - 1 ); + len = min( (int)str.len, DISASM_MAX_PARAM_NAME_LEN - 4 - len ); + break; + } + } default: str = GetType( val ); + len = min( (int)str.len, DISASM_MAX_PARAM_NAME_LEN - 3 ); } - len = STRLEN(" = "); - memcpy( buf, _SC(" = "), sq_rsl(len) ); - buf += len; - - len = min( str.len, DISASM_MAX_PARAM_NAME_LEN - 3 ); #ifdef SQUNICODE - UTF8ToSQUnicode( buf, _bs, str.ptr, str.len ); + UTF8ToSQUnicode( buf, _bs, str.ptr, len ); #else memcpy( buf, str.ptr, sq_rsl(len) ); #endif @@ -18872,51 +19132,54 @@ void SQDebugServer::DebugHook( HSQUIRRELVM vm, int type, { if ( m_pCurVM->_suspended ) { - SQInstruction *pip = m_pCurVM->ci->_ip - 1; - - if ( pip->op == _OP_CALL ) + if ( m_pCurVM->ci->_ip ) { - const SQObjectPtr &val = m_pCurVM->_stack._vals[ m_pCurVM->_stackbase + pip->_arg1 ]; - if ( sq_type(val) == OT_NATIVECLOSURE && - sq_type(_nativeclosure(val)->_name) == OT_STRING && - IsEqual( _SC("suspend"), _string(_nativeclosure(val)->_name) ) ) + SQInstruction *pip = m_pCurVM->ci->_ip - 1; + + if ( pip->op == _OP_CALL ) { - m_nCalls -= (int)( m_pCurVM->ci - m_pCurVM->_callsstack ) + 1; - - switch ( m_State ) + const SQObjectPtr &val = m_pCurVM->_stack._vals[ m_pCurVM->_stackbase + pip->_arg1 ]; + if ( sq_type(val) == OT_NATIVECLOSURE && + sq_type(_nativeclosure(val)->_name) == OT_STRING && + IsEqual( _SC("suspend"), _string(_nativeclosure(val)->_name) ) ) { - case ThreadState_StepOut: + m_nCalls -= (int)( m_pCurVM->ci - m_pCurVM->_callsstack ) + 1; - if ( m_pStateVM != m_pCurVM ) + switch ( m_State ) + { + case ThreadState_StepOut: + + if ( m_pStateVM != m_pCurVM ) + break; + + case ThreadState_StepOver: + + m_State = ThreadState_StepIn; break; - case ThreadState_StepOver: + case ThreadState_StepOutInstruction: - m_State = ThreadState_StepIn; - break; + if ( m_pStateVM != m_pCurVM ) + break; - case ThreadState_StepOutInstruction: + case ThreadState_StepOverInstruction: + case ThreadState_StepInInstruction: - if ( m_pStateVM != m_pCurVM ) + RestoreCachedInstructions(); + ClearCachedInstructions(); + + if ( InstructionStep( vm, ci, 2 ) ) + { + m_State = ThreadState_StepInInstruction; + } + else + { + m_State = ThreadState_NextStatement; + } + + default: break; - - case ThreadState_StepOverInstruction: - case ThreadState_StepInInstruction: - - RestoreCachedInstructions(); - ClearCachedInstructions(); - - if ( InstructionStep( vm, ci, 2 ) ) - { - m_State = ThreadState_StepInInstruction; - } - else - { - m_State = ThreadState_NextStatement; - } - - default: - break; + } } } } @@ -18928,7 +19191,7 @@ void SQDebugServer::DebugHook( HSQUIRRELVM vm, int type, ( IsEqual( _SC("wakeup"), _string(_nativeclosure(m_pCurVM->ci->_closure)->_name) ) || IsEqual( _SC("call"), _string(_nativeclosure(m_pCurVM->ci->_closure)->_name) ) ) ) { - m_nCalls += (int)( vm->ci - vm->_callsstack ) + 1; + m_nCalls += (int)( vm->ci - vm->_callsstack ) + ( type != SQ_HOOK_CALL ); } } } @@ -20302,7 +20565,7 @@ HSQDEBUGSERVER sqdbg_attach_debugger( HSQUIRRELVM vm ) { CDebuggerScriptRef *ref = NULL; - CStackCheck stackcheck( vm ); + STACKCHECK( vm ); sq_pushregistrytable( vm ); sq_pushstring( vm, _SC(SQDBG_SV_TAG), -1 ); @@ -20366,7 +20629,7 @@ HSQDEBUGSERVER sqdbg_attach_debugger( HSQUIRRELVM vm ) void sqdbg_destroy_debugger( HSQUIRRELVM vm ) { - CStackCheck stackcheck( vm ); + STACKCHECK( vm ); sq_pushregistrytable( vm ); sq_pushstring( vm, _SC(SQDBG_SV_TAG), -1 ); diff --git a/sp/src/vscript/sqdbg/sqdbg/str.h b/sp/src/vscript/sqdbg/sqdbg/str.h index e68b8866..c06e1720 100644 --- a/sp/src/vscript/sqdbg/sqdbg/str.h +++ b/sp/src/vscript/sqdbg/sqdbg/str.h @@ -75,6 +75,21 @@ bool atox( string_t str, I *out ); template < typename I > bool atoo( string_t str, I *out ); +template < typename I > +struct _as_unsigned { typedef I T; }; + +template <> +struct _as_unsigned< int > { typedef unsigned int T; }; + +#ifdef _SQ64 +template <> +struct _as_unsigned< SQInteger > { typedef SQUnsignedInteger T; }; +#endif + +#define as_unsigned_type( I ) typename _as_unsigned::T +#define cast_unsigned( I, v ) (as_unsigned_type(I)(v)) +#define IS_UNSIGNED( I ) ((I)0 < (I)-1) + #define _isdigit( c ) \ IN_RANGE_CHAR( c, '0', '9' ) @@ -403,9 +418,10 @@ struct sqstring_t unsigned int i = 0; do { - if ( ptr[i] > 0x7E || other.ptr[i] != (char)ptr[i] ) + if ( (SQUnsignedChar)ptr[i] > 0x7E || other.ptr[i] != (char)ptr[i] ) { - AssertMsg( ptr[i] <= 0x7E, "not implemented" ); + // > 0x7E can be reached through completions request + // unicode identifiers are not supported, ignore them return false; } } @@ -556,6 +572,8 @@ struct stringbufbase_t template < typename I > void PutHex( I value, bool padding = true ) { + STATIC_ASSERT( IS_UNSIGNED( I ) ); + int space = BytesLeft(); if ( space < 3 ) @@ -590,9 +608,9 @@ bool string_t::IsEqualTo( const sqstring_t &other ) const { // Used for comparing against locals and outers, // implement unicode conversion if locals can have unicode characters - if ( other.ptr[i] > 0x7E || (char)other.ptr[i] != ptr[i] ) + if ( (SQUnsignedChar)other.ptr[i] > 0x7E || (char)other.ptr[i] != ptr[i] ) { - AssertMsg( other.ptr[i] <= 0x7E, "not implemented" ); + AssertMsg( (SQUnsignedChar)other.ptr[i] <= 0x7E, "not implemented" ); return false; } } @@ -675,7 +693,7 @@ inline int printint( C *buf, int size, I value ) value /= 10; buf[i--] = !neg ? ( '0' + c ) : ( '0' - c ); } - while ( value && i >= 0 ); + while ( value ); return len; } @@ -683,10 +701,11 @@ inline int printint( C *buf, int size, I value ) template < bool padding, bool prefix, bool uppercase, typename C, typename I > inline int printhex( C *buf, int size, I value ) { + STATIC_ASSERT( IS_UNSIGNED( as_unsigned_type( I ) ) ); Assert( buf ); Assert( size > 0 ); - int len = ( prefix ? 2 : 0 ) + ( padding ? sizeof(I) * 2 : countdigits<16>( value ) ); + int len = ( prefix ? 2 : 0 ) + ( padding ? sizeof(I) * 2 : countdigits<16>( cast_unsigned( I, value ) ) ); if ( len > size ) len = size; @@ -695,11 +714,11 @@ inline int printhex( C *buf, int size, I value ) do { - C c = value & 0xf; - value >>= 4; + C c = cast_unsigned( I, value ) & 0xf; + *(as_unsigned_type(I)*)&value >>= 4; buf[i--] = c + ( ( c < 10 ) ? '0' : ( ( uppercase ? 'A' : 'a' ) - 10 ) ); } - while ( value && i >= 0 ); + while ( value ); if ( padding ) { @@ -725,6 +744,7 @@ inline int printhex( C *buf, int size, I value ) template < typename C, typename I > inline int printoct( C *buf, int size, I value ) { + STATIC_ASSERT( IS_UNSIGNED( I ) ); Assert( buf ); Assert( size > 0 ); @@ -741,7 +761,7 @@ inline int printoct( C *buf, int size, I value ) value >>= 3; buf[i--] = '0' + c; } - while ( value && i >= 0 ); + while ( value ); if ( i >= 0 ) buf[i--] = '0'; @@ -1302,7 +1322,7 @@ doescape: else { mbc[bytes++] = 'x'; - bytes += printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQChar)cp ); + bytes += printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQUnsignedChar)cp ); } goto write; @@ -1339,7 +1359,7 @@ x7ff: mbc[bytes++] = '\\'; mbc[bytes++] = 'x'; - bytes = bytes + printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQChar)cp ); + bytes = bytes + printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQUnsignedChar)cp ); goto write; } } diff --git a/sp/src/vscript/sqdbg/sqdbg/vec.h b/sp/src/vscript/sqdbg/sqdbg/vec.h index a6073acb..a8c7488e 100644 --- a/sp/src/vscript/sqdbg/sqdbg/vec.h +++ b/sp/src/vscript/sqdbg/sqdbg/vec.h @@ -306,7 +306,7 @@ public: void Free( void *ptr ) { - Assert( !SEQUENTIAL ); + STATIC_ASSERT( !SEQUENTIAL ); Assert( m_Memory ); Assert( ptr ); @@ -364,7 +364,7 @@ public: void ReleaseShrink() { - Assert( SEQUENTIAL ); + STATIC_ASSERT( SEQUENTIAL ); if ( !m_Memory ) return; @@ -412,7 +412,7 @@ public: void Release() { - Assert( SEQUENTIAL ); + STATIC_ASSERT( SEQUENTIAL ); if ( !m_Memory || ( !m.LastFreeChunk() && !m.LastFreeIndex() ) ) return; @@ -437,7 +437,7 @@ public: void ReleaseTop() { - Assert( SEQUENTIAL ); + STATIC_ASSERT( SEQUENTIAL ); m.SetLastFreeChunk( m.PrevChunk() ); m.SetLastFreeIndex( m.PrevIndex() ); @@ -455,23 +455,23 @@ public: vector() : base(), size(0) { - Assert( !bExternalMem ); + STATIC_ASSERT( !bExternalMem ); } vector( CAllocator &a ) : base(a), size(0) { - Assert( bExternalMem ); + STATIC_ASSERT( bExternalMem ); } vector( I count ) : base(), size(0) { - Assert( !bExternalMem ); + STATIC_ASSERT( !bExternalMem ); base.Alloc( count * sizeof(T) ); } vector( const vector< T > &src ) : base() { - Assert( !bExternalMem ); + STATIC_ASSERT( !bExternalMem ); base.Alloc( src.base.Size() ); size = src.size;