mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-07-27 07:31:49 +03:00
Update sqdbg
This commit is contained in:
parent
985ebc0dbb
commit
ab03538347
@ -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 <tier0/dbg.h>
|
||||
|
||||
#define STATIC_ASSERT COMPILE_TIME_ASSERT
|
||||
|
||||
// Misdefined for GCC in platform.h
|
||||
#undef UNREACHABLE
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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 ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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,13 +138,23 @@ void sqdbg_sleep( int ms )
|
||||
#define _SC(s) s
|
||||
#endif
|
||||
|
||||
#if defined(SQUNICODE) && !defined(WCHAR_SIZE)
|
||||
#ifdef _WIN32
|
||||
#ifdef SQUNICODE
|
||||
#ifdef _WIN32
|
||||
#ifndef WCHAR_SIZE
|
||||
#define WCHAR_SIZE 2
|
||||
#else
|
||||
#endif
|
||||
typedef uint16_t SQUnsignedChar;
|
||||
#else
|
||||
#ifndef WCHAR_SIZE
|
||||
#define WCHAR_SIZE 4
|
||||
#endif
|
||||
typedef uint32_t SQUnsignedChar;
|
||||
#endif
|
||||
#else
|
||||
typedef unsigned char SQUnsignedChar;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
STATIC_ASSERT( sizeof(SQChar) == sizeof(SQUnsignedChar) );
|
||||
|
||||
#ifndef scstrlen
|
||||
#ifdef SQUNICODE
|
||||
@ -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,
|
||||
@ -6286,10 +6351,20 @@ void SQDebugServer::DescribeInstruction( const SQInstruction *instr, const SQFun
|
||||
switch ( instr->op )
|
||||
{
|
||||
case _OP_LOADNULLS:
|
||||
{
|
||||
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,29 +12832,45 @@ 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;
|
||||
|
||||
AssertClient( expression.ptr[-1] == '[' );
|
||||
char *pIdx = strchr( expression.ptr, ']' );
|
||||
string_t strFrame( expression.ptr, pIdx - expression.ptr );
|
||||
|
||||
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 ) &&
|
||||
idx >= 0 && idx < (int)ref->GetThread()->_stack.size() )
|
||||
{
|
||||
if ( !strtoint( expression, &idx ) ||
|
||||
stackbase + idx < 0 || stackbase + idx >= (int)vm->_stack.size() )
|
||||
return false;
|
||||
|
||||
out.type = objref_t::PTR;
|
||||
out.ptr = &ref->GetThread()->_stack._vals[idx];
|
||||
out.ptr = &vm->_stack._vals[ stackbase + idx ];
|
||||
value = *out.ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
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
|
||||
if ( sq_type(target) == OT_CLOSURE )
|
||||
#endif
|
||||
#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
|
||||
{
|
||||
#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,17 +15861,42 @@ 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 )
|
||||
if ( callframe < vm->_callsstacksize )
|
||||
{
|
||||
stackbase = next;
|
||||
|
||||
if ( callframe + 1 < vm->_callsstacksize )
|
||||
{
|
||||
next = stackbase + vm->_callsstack[ callframe + 1 ]._prevstkbase;
|
||||
}
|
||||
else
|
||||
{
|
||||
next = max;
|
||||
}
|
||||
}
|
||||
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();
|
||||
@ -15693,16 +15906,28 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq
|
||||
|
||||
if ( !( flags & kFS_Hexadecimal ) )
|
||||
{
|
||||
name.PutInt( i );
|
||||
name.PutInt( callframe );
|
||||
}
|
||||
else
|
||||
{
|
||||
name.PutHex( i, false );
|
||||
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 ( stackbase == i )
|
||||
if ( idx == stackbase )
|
||||
{
|
||||
name.Put('*');
|
||||
|
||||
@ -15722,11 +15947,8 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( ++callframe < vm->_callsstacksize )
|
||||
stackbase += vm->_callsstack[callframe]._prevstkbase;
|
||||
}
|
||||
else if ( vm->_top == i )
|
||||
else if ( vm->_top == idx )
|
||||
{
|
||||
name.Put('_');
|
||||
}
|
||||
@ -15737,6 +15959,10 @@ void SQDebugServer::OnRequest_Variables( const json_table_t &arguments, int seq
|
||||
if ( ShouldPageArray( val, 16 * ARRAY_PAGE_LIMIT ) )
|
||||
elem.SetInt( "indexedVariables", (int)_array(val)->_values.size() );
|
||||
}
|
||||
|
||||
if ( next == max )
|
||||
break;
|
||||
}
|
||||
DAP_SEND();
|
||||
|
||||
break;
|
||||
@ -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;
|
||||
|
||||
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
|
||||
@ -18871,6 +19131,8 @@ void SQDebugServer::DebugHook( HSQUIRRELVM vm, int type,
|
||||
if ( m_pCurVM->ci )
|
||||
{
|
||||
if ( m_pCurVM->_suspended )
|
||||
{
|
||||
if ( m_pCurVM->ci->_ip )
|
||||
{
|
||||
SQInstruction *pip = m_pCurVM->ci->_ip - 1;
|
||||
|
||||
@ -18921,6 +19183,7 @@ void SQDebugServer::DebugHook( HSQUIRRELVM vm, int type,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sq_type(m_pCurVM->ci->_closure) == OT_NATIVECLOSURE &&
|
||||
@ -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 );
|
||||
|
@ -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<I>::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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user