issue #82 improve support for drilling down into variables

gccjit-ravi534
Dibyendu Majumdar 8 years ago
parent 7912fdee63
commit 8e003007a6

@ -689,6 +689,9 @@ void vscode_serialize_response_new(membuff_t *mb, ProtocolMessage *res) {
membuff_add_string(mb, "{\"name\":\"");
membuff_add_string(
mb, res->u.Response.u.VariablesResponse.variables[d].name);
membuff_add_string(mb, "\",\"type\":\"");
membuff_add_string(
mb, res->u.Response.u.VariablesResponse.variables[d].type);
membuff_add_string(mb, "\",\"variablesReference\":");
membuff_add_longlong(mb, res->u.Response.u.VariablesResponse.variables[d]
.variablesReference);
@ -902,31 +905,31 @@ void vscode_string_copy(char *buf, const char *src, size_t buflen) {
int64_t vscode_pack(PackedInteger *pi) {
int64_t i = 0;
assert(pi->a8 <= 0xFF);
assert(pi->b8 <= 0xFF);
assert(pi->c8 <= 0xFF);
assert(pi->d8 <= 0xFF);
assert(pi->e8 <= 0xFF);
assert(pi->f8 <= 0xFF);
assert(pi->g4 <= 0x0F);
i |= (pi->a8 & 0xFF);
i |= ((int64_t)(pi->b8 & 0xFF) << 8);
i |= ((int64_t)(pi->c8 & 0xFF) << 16);
i |= ((int64_t)(pi->d8 & 0xFF) << 24);
i |= ((int64_t)(pi->e8 & 0xFF) << 32);
i |= ((int64_t)(pi->f8 & 0xFF) << 40);
i |= ((int64_t)(pi->g4 & 0x0F) << 48);
assert(pi->x8[0] <= 0xFF);
assert(pi->x8[1] <= 0xFF);
assert(pi->x8[2] <= 0xFF);
assert(pi->x8[3] <= 0xFF);
assert(pi->x8[4] <= 0xFF);
assert(pi->depth <= 0xFF);
assert(pi->vartype <= 0x0F);
i |= (pi->x8[0] & 0xFF);
i |= ((int64_t)(pi->x8[1] & 0xFF) << 8);
i |= ((int64_t)(pi->x8[2] & 0xFF) << 16);
i |= ((int64_t)(pi->x8[3] & 0xFF) << 24);
i |= ((int64_t)(pi->x8[4] & 0xFF) << 32);
i |= ((int64_t)(pi->depth & 0xFF) << 40);
i |= ((int64_t)(pi->vartype & 0x0F) << 48);
return i;
}
void vscode_unpack(int64_t i, PackedInteger *pi) {
int64_t mask = 0xFF;
pi->a8 = (unsigned int)(i & mask); mask <<= 8;
pi->b8 = (unsigned int)((i & mask) >> 8); mask <<= 8;
pi->c8 = (unsigned int)((i & mask) >> 16); mask <<= 8;
pi->d8 = (unsigned int)((i & mask) >> 24); mask <<= 8;
pi->e8 = (unsigned int)((i & mask) >> 32); mask <<= 8;
pi->f8 = (unsigned int)((i & mask) >> 40); mask <<= 8;
pi->g4 = (unsigned int)(((i & mask) >> 48) & 0x0F);
pi->x8[0] = (unsigned int)(i & mask); mask <<= 8;
pi->x8[1] = (unsigned int)((i & mask) >> 8); mask <<= 8;
pi->x8[2] = (unsigned int)((i & mask) >> 16); mask <<= 8;
pi->x8[3] = (unsigned int)((i & mask) >> 24); mask <<= 8;
pi->x8[4] = (unsigned int)((i & mask) >> 32); mask <<= 8;
pi->depth = (unsigned int)((i & mask) >> 40); mask <<= 8;
pi->vartype = (unsigned int)(((i & mask) >> 48) & 0x0F);
}

@ -103,13 +103,9 @@ The integer 4503599627370495 takes up 52 bits - so that means 6 8-bit values and
4-bit value can be accomodated.
*/
typedef struct {
unsigned int a8;
unsigned int b8;
unsigned int c8;
unsigned int d8;
unsigned int e8;
unsigned int f8;
unsigned int g4;
unsigned int x8[5];
unsigned int depth;
unsigned int vartype;
} PackedInteger;
typedef struct {
@ -144,6 +140,7 @@ typedef struct {
typedef struct {
char name[NAME_LEN];
char type[NAME_LEN];
char value[VALUE_LEN];
int64_t variablesReference;
} Variable;

@ -8,19 +8,19 @@
*/
#include <assert.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef _WIN32
#include <direct.h>
#include <fcntl.h>
#include <io.h>
#define chdir _chdir
/* When debugging
/* When debugging
#include <windows.h>
*/
#else
@ -35,9 +35,10 @@
/* debugger state */
enum {
DEBUGGER_BIRTH = 1, /* Initial state */
DEBUGGER_BIRTH = 1, /* Initial state */
DEBUGGER_INITIALIZED = 2, /* Have processed VSCode initialize request */
DEBUGGER_PROGRAM_LAUNCHED = 3, /* Have processed VSCode launch request - Lua program running */
DEBUGGER_PROGRAM_LAUNCHED =
3, /* Have processed VSCode launch request - Lua program running */
DEBUGGER_PROGRAM_STEPPING = 4, /* In stepping mode */
DEBUGGER_PROGRAM_RUNNING = 5, /* In continue mode - will stop at breakpoint */
DEBUGGER_PROGRAM_STOPPED = 6, /* Have hit a break point */
@ -46,56 +47,30 @@ enum {
/* sub states of DEBUGGER_PROGRAM_STEPPING */
enum {
DEBUGGER_STEPPING_IN = 1, /* Step into */
DEBUGGER_STEPPING_IN = 1, /* Step into */
DEBUGGER_STEPPING_OVER = 2, /* Step over */
DEBUGGER_STEPPING_OUT = 3 /* Step out of the current function */
DEBUGGER_STEPPING_OUT = 3 /* Step out of the current function */
};
/* Following values must fit into 2 bits and 0 is not a valid value */
enum { VAR_TYPE_LOCALS = 1, VAR_TYPE_VARARGS = 2, VAR_TYPE_UPVALUES = 3, VAR_TYPE_GLOBALS = 4, VAR_LUA_GLOBALS = 5 };
enum {
VAR_TYPE_LOCALS = 1,
VAR_TYPE_VARARGS = 2,
VAR_TYPE_UPVALUES = 3,
VAR_TYPE_GLOBALS = 4,
VAR_LUA_GLOBALS = 5
};
/* Lua globals names - we use this to split globals into two lists */
static const char *lua_globals[] = {
"ipairs",
"error",
"utf8",
"rawset",
"tostring",
"select",
"tonumber",
"_VERSION",
"loadfile",
"xpcall",
"string",
"rawlen",
"ravitype",
"print",
"rawequal",
"setmetatable",
"require",
"getmetatable",
"next",
"package",
"coroutine",
"io",
"_G",
"math",
"collectgarbage",
"os",
"table",
"ravi",
"dofile",
"pcall",
"load",
"module",
"rawget",
"debug",
"assert",
"type",
"pairs",
"bit32",
NULL
};
"ipairs", "error", "utf8", "rawset", "tostring",
"select", "tonumber", "_VERSION", "loadfile", "xpcall",
"string", "rawlen", "ravitype", "print", "rawequal",
"setmetatable", "require", "getmetatable", "next", "package",
"coroutine", "io", "_G", "math", "collectgarbage",
"os", "table", "ravi", "dofile", "pcall",
"load", "module", "rawget", "debug", "assert",
"type", "pairs", "bit32", NULL};
typedef struct {
int depth;
@ -108,8 +83,10 @@ typedef struct {
* evolving this is easier to work with.
*/
static FILE *my_logger = NULL;
static int thread_event_sent = 0; /* Set to 1 once we have sent a thread event to VSCode */
static int debugger_state = DEBUGGER_BIRTH; /* Debugger's state is tracked in this variable */
static int thread_event_sent =
0; /* Set to 1 once we have sent a thread event to VSCode */
static int debugger_state =
DEBUGGER_BIRTH; /* Debugger's state is tracked in this variable */
static Breakpoint breakpoints[MAX_TOTAL_BREAKPOINTS];
static ProtocolMessage req, res;
static ProtocolMessage output_response;
@ -119,8 +96,11 @@ static SourceOnStack sourceOnStack[MAX_STACK_FRAMES];
static int sourceOnStackCount = 0;
/* Following three are for the three differet stepping modes */
static int stepping_mode = DEBUGGER_STEPPING_IN; /* default */
static int stepping_stacklevel = -1; /* This tracks the stack level from where a step over or step out was requested */
static lua_State *stepping_lua_State = NULL; /* Tracks the Lua State that requested a step over or step out */
static int stepping_stacklevel =
-1; /* This tracks the stack level from where a step over or step out was
requested */
static lua_State *stepping_lua_State =
NULL; /* Tracks the Lua State that requested a step over or step out */
static membuff_t readbuf;
/*
@ -169,15 +149,18 @@ static void handle_thread_request(ProtocolMessage *req, ProtocolMessage *res,
/* Takes an intptr_t value and make sure that it will
* fit into a double without loss - which is what is used to represent a
* number in JSON and JavaScript.
* number in JSON and JavaScript.
*/
static inline intptr_t ensure_value_fits_in_mantissa(intptr_t sourceReference) {
/* pointer values are less than 53 bits anyway so nothing to do, but we assert just in case */
/* pointer values are less than 53 bits anyway so nothing to do, but we assert
* just in case */
assert(sourceReference <= 9007199254740991);
return sourceReference;
}
static void get_path_and_name(char *path, size_t pathlen, char *name, size_t namelen, const char *input_name, const char *workingdir) {
static void get_path_and_name(char *path, size_t pathlen, char *name,
size_t namelen, const char *input_name,
const char *workingdir) {
/* If the source does not include a path then
we prefix the source with the path to the
working directrory so that it can be reliably
@ -189,8 +172,7 @@ static void get_path_and_name(char *path, size_t pathlen, char *name, size_t nam
/* source includes a path */
vscode_string_copy(name, last_path_delim + 1, namelen);
vscode_string_copy(path, input_name, pathlen);
}
else {
} else {
/* prepend the working directory to the name */
vscode_string_copy(name, input_name, namelen);
if (workingdir[0]) {
@ -199,8 +181,7 @@ static void get_path_and_name(char *path, size_t pathlen, char *name, size_t nam
snprintf(path, pathlen, "%s%s", workingdir, input_name);
else
snprintf(path, pathlen, "%s/%s", workingdir, input_name);
}
else {
} else {
/* no working directory */
vscode_string_copy(path, input_name, pathlen);
}
@ -240,8 +221,7 @@ static void handle_stack_trace_request(ProtocolMessage *req,
res->u.Response.u.StackTraceResponse.stackFrames[depth].source.name,
name, sizeof res->u.Response.u.StackTraceResponse.stackFrames[depth]
.source.name);
}
else if (memcmp(src, "=[C]", 4) == 0) {
} else if (memcmp(src, "=[C]", 4) == 0) {
/* C Function so source is not available */
res->u.Response.u.StackTraceResponse.stackFrames[depth]
.source.sourceReference = -1;
@ -250,8 +230,7 @@ static void handle_stack_trace_request(ProtocolMessage *req,
"<C function>",
sizeof res->u.Response.u.StackTraceResponse.stackFrames[depth]
.source.name);
}
else {
} else {
/* Source is a string - send a reference to the stack frame */
/* Currently (as ov VSCode 1.1 the sourceReference must be unique within
* a debug session. A cheap way of making this unique is to use the
@ -311,7 +290,8 @@ static void handle_source_request(ProtocolMessage *req, ProtocolMessage *res,
}
/*
fprintf(my_logger,
"SEARCHED FOR sourceReference=%" PRId64 ", found at stack depth = %d\n",
"SEARCHED FOR sourceReference=%" PRId64 ", found at stack depth =
%d\n",
sourceReference, depth);
*/
vscode_make_success_response(req, res, VSCODE_SOURCE_RESPONSE);
@ -322,19 +302,16 @@ static void handle_source_request(ProtocolMessage *req, ProtocolMessage *res,
if (*src != '@' && *src != '=') {
/* Source is a string */
vscode_string_copy(res->u.Response.u.SourceResponse.content, src,
sizeof res->u.Response.u.SourceResponse.content);
}
else
sizeof res->u.Response.u.SourceResponse.content);
} else
goto l_nosource;
}
else
} else
goto l_nosource;
}
else {
} else {
l_nosource:
vscode_string_copy(res->u.Response.u.SourceResponse.content,
"Source not available",
sizeof res->u.Response.u.SourceResponse.content);
"Source not available",
sizeof res->u.Response.u.SourceResponse.content);
}
vscode_send(res, out, my_logger);
}
@ -366,11 +343,12 @@ static void handle_set_breakpoints_request(ProtocolMessage *req,
strcmp(breakpoints[y].source.path,
req->u.Request.u.SetBreakpointsRequest.source.path) == 0) {
vscode_string_copy(breakpoints[y].source.path,
req->u.Request.u.SetBreakpointsRequest.source.path,
sizeof breakpoints[0].source.path);
req->u.Request.u.SetBreakpointsRequest.source.path,
sizeof breakpoints[0].source.path);
breakpoints[y].line =
req->u.Request.u.SetBreakpointsRequest.breakpoints[i].line;
/* fprintf(my_logger, "Saving breakpoint j=%d, k=%d, i=%d\n", y, k, i); */
/* fprintf(my_logger, "Saving breakpoint j=%d, k=%d, i=%d\n", y, k,
* i); */
if (k < MAX_BREAKPOINTS) {
res->u.Response.u.SetBreakpointsResponse.breakpoints[k].line =
req->u.Request.u.SetBreakpointsRequest.breakpoints[i].line;
@ -405,7 +383,7 @@ static void handle_set_breakpoints_request(ProtocolMessage *req,
* Handle ScopesRequest
* Since VSCode requires us to send a numeric references we need
* to encode the stack depth and the scope within a numeric value.
* We do this by packing the values into an int32_t value.
* We do this by packing the values into an double value.
*/
static void handle_scopes_request(ProtocolMessage *req, ProtocolMessage *res,
lua_State *L, FILE *out) {
@ -417,43 +395,49 @@ static void handle_scopes_request(ProtocolMessage *req, ProtocolMessage *res,
int status = lua_getinfo(L, "u", &entry);
assert(status);
int i = 0;
vscode_string_copy(res->u.Response.u.ScopesResponse.scopes[i].name, "Locals",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
vscode_string_copy(res->u.Response.u.ScopesResponse.scopes[i].name,
"Locals",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
PackedInteger varRef;
memset(&varRef, 0, sizeof(PackedInteger));
varRef.g4 = (unsigned int) VAR_TYPE_LOCALS;
varRef.f8 = (unsigned int) depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference = vscode_pack(&varRef);
varRef.vartype = (unsigned int)VAR_TYPE_LOCALS;
varRef.depth = (unsigned int)depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference =
vscode_pack(&varRef);
res->u.Response.u.ScopesResponse.scopes[i].expensive = 0;
i++;
if (entry.isvararg) {
vscode_string_copy(res->u.Response.u.ScopesResponse.scopes[i].name,
"Var Args",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
vscode_string_copy(
res->u.Response.u.ScopesResponse.scopes[i].name, "Var Args",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
memset(&varRef, 0, sizeof(PackedInteger));
varRef.g4 = (unsigned int)VAR_TYPE_VARARGS;
varRef.f8 = (unsigned int)depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference = vscode_pack(&varRef);
varRef.vartype = (unsigned int)VAR_TYPE_VARARGS;
varRef.depth = (unsigned int)depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference =
vscode_pack(&varRef);
res->u.Response.u.ScopesResponse.scopes[i].expensive = 0;
i++;
}
vscode_string_copy(res->u.Response.u.ScopesResponse.scopes[i].name, "Globals",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
vscode_string_copy(res->u.Response.u.ScopesResponse.scopes[i].name,
"Globals",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
memset(&varRef, 0, sizeof(PackedInteger));
varRef.g4 = (unsigned int)VAR_TYPE_GLOBALS;
varRef.f8 = (unsigned int)depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference = vscode_pack(&varRef);
varRef.vartype = (unsigned int)VAR_TYPE_GLOBALS;
varRef.depth = (unsigned int)depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference =
vscode_pack(&varRef);
res->u.Response.u.ScopesResponse.scopes[i].expensive = 0;
i++;
vscode_string_copy(res->u.Response.u.ScopesResponse.scopes[i].name, "Lua Globals",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
vscode_string_copy(res->u.Response.u.ScopesResponse.scopes[i].name,
"Lua Globals",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
memset(&varRef, 0, sizeof(PackedInteger));
varRef.g4 = (unsigned int)VAR_LUA_GLOBALS;
varRef.f8 = (unsigned int)depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference = vscode_pack(&varRef);
varRef.vartype = (unsigned int)VAR_LUA_GLOBALS;
varRef.depth = (unsigned int)depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference =
vscode_pack(&varRef);
res->u.Response.u.ScopesResponse.scopes[i].expensive = 0;
}
else {
} else {
vscode_make_error_response(req, res, VSCODE_SCOPES_RESPONSE,
"Error retrieving stack frame");
}
@ -493,10 +477,9 @@ static void get_table_info(lua_State *L, int stack_idx, char *buf, size_t len) {
// Get information regarding a Lua userdata value
static void get_userdata(lua_State *L, int stack_idx, char *buf, size_t len) {
const char *udata = raviL_tolstring(L, stack_idx, NULL);
vscode_json_stringify(udata, buf, len);
lua_pop(L, 1); /* remove result from raviL_tolstring() */
lua_pop(L, 1); /* remove result from raviL_tolstring() */
}
// Get information regarding a Lua value
@ -528,7 +511,7 @@ static int get_value(lua_State *L, int stack_idx, char *buf, size_t len) {
}
case LUA_TSTRING: {
char tbuf[1024];
// We assume here that the value at stack index is safe to convert
// We assume here that the value at stack index is safe to convert
// to a string
snprintf(tbuf, sizeof tbuf, "%s", lua_tostring(L, stack_idx));
vscode_json_stringify(tbuf, buf, len);
@ -556,31 +539,60 @@ static int get_value(lua_State *L, int stack_idx, char *buf, size_t len) {
}
static int search_for_name(const char *name, const char **filter) {
if (filter == NULL)
return 0;
if (filter == NULL) return 0;
for (int i = 0; filter[i] != NULL; i++)
if (strcmp(name, filter[i]) == 0)
return 1;
if (strcmp(name, filter[i]) == 0) return 1;
return 0;
}
static const char *var_type_as_string(int vtype) {
switch (vtype) {
case VAR_TYPE_LOCALS:
return "locals";
case VAR_TYPE_VARARGS:
return "varargs";
case VAR_TYPE_UPVALUES:
return "upvalues";
case VAR_TYPE_GLOBALS:
return "globals";
case VAR_LUA_GLOBALS:
return "Lua globals";
default:
return "invalid";
}
}
/*
* Get a table's values into the response
*/
static void get_table_values(ProtocolMessage *res, lua_State *L, int stack_idx,
int varType, int depth, int add_var_reference, const char **filter) {
const PackedInteger *parent, int depth,
int add_var_reference, const char **filter) {
// Push another reference to the table on top of the stack (so we know
// where it is, and this function can work for negative, positive and
// pseudo indices
// pseudo indices
lua_pushvalue(L, stack_idx);
// stack now contains: -1 => table
lua_pushnil(L); // push first key
/* stack now contains: -1 => nil (key); -2 => table */
int v = 1; /* v is the position of key in table from iterator point of view */
int j = 0; /* j is the index in response */
assert(depth <= 5);
int var = depth == 5 ? 0 : parent->x8[depth];
fprintf(my_logger, "get_table_values() --> depth = %d var request = %d\n",
depth, var);
while (lua_next(L, -2) && j < MAX_VARIABLES) {
// stack now contains: -1 => value; -2 => key; -3 => table
if (j+1 == MAX_VARIABLES) {
if (var != 0) {
/* drill down if we are on the requested variable */
if (v == var && lua_type(L, -1) == LUA_TTABLE && depth < 5) {
fprintf(my_logger,
"get_table_values() --> drilling down var request = %d\n", var);
get_table_values(res, L, -1, parent, depth + 1, true, filter);
}
lua_pop(L, 1);
} else if (j + 1 == MAX_VARIABLES) {
vscode_string_copy(
res->u.Response.u.VariablesResponse.variables[j].name, "...",
sizeof res->u.Response.u.VariablesResponse.variables[0].name);
@ -588,8 +600,7 @@ static void get_table_values(ProtocolMessage *res, lua_State *L, int stack_idx,
res->u.Response.u.VariablesResponse.variables[j].value, "",
sizeof res->u.Response.u.VariablesResponse.variables[0].value);
lua_pop(L, 1); /* pop value */
}
else {
} else {
// stack now contains: -1 => value; -2 => key; -3 => table
// copy the key so that lua_tostring does not modify the
// original
@ -598,22 +609,39 @@ static void get_table_values(ProtocolMessage *res, lua_State *L, int stack_idx,
char key[sizeof res->u.Response.u.VariablesResponse.variables[0].name];
get_value(L, -1, key, sizeof key);
if (!search_for_name(key, filter)) {
vscode_string_copy(res->u.Response.u.VariablesResponse.variables[j].name, key,
sizeof res->u.Response.u.VariablesResponse.variables[0].name);
vscode_string_copy(
res->u.Response.u.VariablesResponse.variables[j].name, key,
sizeof res->u.Response.u.VariablesResponse.variables[0].name);
vscode_string_copy(
res->u.Response.u.VariablesResponse.variables[j].type,
ravi_typename(L, -2),
sizeof res->u.Response.u.VariablesResponse.variables[0].type);
int is_table = get_value(
L, -2, res->u.Response.u.VariablesResponse.variables[j].value,
sizeof res->u.Response.u.VariablesResponse.variables[0].value);
if (is_table && add_var_reference) {
L, -2, res->u.Response.u.VariablesResponse.variables[j].value,
sizeof res->u.Response.u.VariablesResponse.variables[0].value);
if (is_table && add_var_reference && depth < 5) {
PackedInteger pi;
memset(&pi, 0, sizeof pi);
pi.g4 = varType;
pi.f8 = depth;
pi.e8 = v; /* cannot be zero based !*/
res->u.Response.u.VariablesResponse.variables[j].variablesReference = vscode_pack(&pi);
}
else {
/* Right now we do not support further drill down */
res->u.Response.u.VariablesResponse.variables[j].variablesReference = 0;
pi.vartype = parent->vartype; /* vartype */
pi.depth = parent->depth; /* depth */
/* Copy the indices reported by the previous call */
for (int i = 0; i < depth; i++) pi.x8[i] = parent->x8[i];
assert(depth >= 0 && depth < 5);
pi.x8[depth] = v; /* cannot be zero based !*/
fprintf(my_logger,
"Encoding table index [%s] as vartype=%s depth=%u %u %u %u "
"%u %d\n",
key, var_type_as_string(pi.vartype), pi.depth, pi.x8[0],
pi.x8[1], pi.x8[2], pi.x8[3], pi.x8[4]);
res->u.Response.u.VariablesResponse.variables[j].variablesReference =
vscode_pack(&pi);
fprintf(my_logger, "Key %s variable reference %lld\n", key,
res->u.Response.u.VariablesResponse.variables[j]
.variablesReference);
} else {
/* We do not support further drill down */
res->u.Response.u.VariablesResponse.variables[j].variablesReference =
0;
}
j++;
}
@ -642,6 +670,11 @@ static void handle_variables_request(ProtocolMessage *req, ProtocolMessage *res,
PackedInteger pi;
memset(&pi, 0, sizeof pi);
vscode_unpack(varRef, &pi);
fprintf(my_logger,
"Unpacked variable reference to vartype=%s depth=%u %u %u %u %u %d\n",
var_type_as_string(pi.vartype), pi.depth, pi.x8[0], pi.x8[1],
pi.x8[2], pi.x8[3], pi.x8[4]);
/*
* The variable reference is encoded such that it contains:
* type (4 bits) - the scope type
@ -649,38 +682,42 @@ static void handle_variables_request(ProtocolMessage *req, ProtocolMessage *res,
* var (8 bits) - the index of the variable as provided to lua_getlocal()
* - These are negative for varargs values
*/
int type = pi.g4;
int depth = pi.f8;
int var = pi.e8;
int type = pi.vartype;
int depth = pi.depth;
int var = pi.x8[0];
int isvararg = type == VAR_TYPE_VARARGS;
//fprintf(my_logger, "Var Request --> %d isvararg=%d\n", type, isvararg);
// fprintf(my_logger, "Var Request --> %d isvararg=%d\n", type, isvararg);
if (lua_getstack(L, depth, &entry)) {
if (type == VAR_TYPE_GLOBALS || type == VAR_LUA_GLOBALS) {
if (var == 0) {
/* top level */
lua_pushglobaltable(L);
int stack_idx = lua_gettop(L);
get_table_values(res, L, stack_idx, type, depth, true, type == VAR_TYPE_GLOBALS ? lua_globals: NULL);
/* depth is set to 0 as there is no local scope variable */
get_table_values(res, L, stack_idx, &pi, 0, true,
type == VAR_TYPE_GLOBALS ? lua_globals : NULL);
lua_pop(L, 1);
}
else {
} else {
/* The request is to expand an entry in the global table */
/* var is the position of key in global table */
int checktop = lua_gettop(L);
lua_pushglobaltable(L);
/* stack now contains: -1 => table */
lua_pushnil(L); /* push first key */
/* stack now contains: -1 => nil (key); -2 => table */
int v = 1; /* v is the position of key in table from iterator point of view */
lua_pushnil(L); /* push first key */
/* stack now contains: -1 => nil (key); -2 => table */
int v = 1; /* v is the position of key in table from iterator point of
view */
while (lua_next(L, -2)) {
if (v == var) {
/* We found the value we need to expand - we know already this is a table */
/* We found the value we need to expand - we know already this is a
* table */
int current_top = lua_gettop(L);
int l_type = lua_type(L, current_top);
/* We know this should be a table but we check for safety */
assert(l_type == LUA_TTABLE);
if (l_type == LUA_TTABLE) {
get_table_values(res, L, current_top, type, depth, false, NULL);
/* depth set to 1 as 0 is taken by global reference */
get_table_values(res, L, current_top, &pi, 1, true, NULL);
}
/* TODO we can break the loop here */
}
@ -690,8 +727,8 @@ static void handle_variables_request(ProtocolMessage *req, ProtocolMessage *res,
lua_pop(L, 1); /* pop global table */
assert(lua_gettop(L) == checktop);
}
}
else if (type == VAR_TYPE_LOCALS || type == VAR_TYPE_VARARGS) { /* locals */
} else if (type == VAR_TYPE_LOCALS ||
type == VAR_TYPE_VARARGS) { /* locals */
if (var == 0) {
/*
* A top level request - i.e. from the scope
@ -703,8 +740,7 @@ static void handle_variables_request(ProtocolMessage *req, ProtocolMessage *res,
res->u.Response.u.VariablesResponse.variables[v].name, "...",
sizeof res->u.Response.u.VariablesResponse.variables[0].name);
vscode_string_copy(
res->u.Response.u.VariablesResponse.variables[v].value,
"",
res->u.Response.u.VariablesResponse.variables[v].value, "",
sizeof res->u.Response.u.VariablesResponse.variables[0].value);
break;
}
@ -721,8 +757,7 @@ static void handle_variables_request(ProtocolMessage *req, ProtocolMessage *res,
res->u.Response.u.VariablesResponse.variables[v].name, temp,
sizeof res->u.Response.u.VariablesResponse.variables[0]
.name);
}
else {
} else {
vscode_string_copy(
res->u.Response.u.VariablesResponse.variables[v].name, name,
sizeof res->u.Response.u.VariablesResponse.variables[0]
@ -733,52 +768,50 @@ static void handle_variables_request(ProtocolMessage *req, ProtocolMessage *res,
res->u.Response.u.VariablesResponse.variables[v].value,
sizeof res->u.Response.u.VariablesResponse.variables[0]
.value);
vscode_string_copy(
res->u.Response.u.VariablesResponse.variables[v].type,
ravi_typename(L, -1),
sizeof res->u.Response.u.VariablesResponse.variables[0].type);
if (is_table) {
/* If the variable is a table then we pass pack a reference
that is used by the front end to drill down */
PackedInteger newref;
memset(&newref, 0, sizeof newref);
newref.g4 = type;
newref.f8 = depth;
newref.e8 = n;
newref.vartype = type;
newref.depth = depth;
newref.x8[0] = n; /* local variable reference at depth 0 */
res->u.Response.u.VariablesResponse.variables[v]
.variablesReference = vscode_pack(&newref);
}
else {
.variablesReference = vscode_pack(&newref);
} else {
/* not a table */
res->u.Response.u.VariablesResponse.variables[v]
.variablesReference = 0;
.variablesReference = 0;
}
v++;
}
lua_pop(L, 1); /* pop the value */
}
else {
} else {
break;
}
}
}
else {
} else /* var != 0 */ {
/*
* We support one level of drill down
* drill down
*/
/* fprintf(my_logger,
"\n--> Request to extract local variable %d of type %d at "
"depth %d\n",
var, type, depth); */
const char *name = lua_getlocal(L, &entry, type == VAR_TYPE_VARARGS ? -var : var);
const char *name =
lua_getlocal(L, &entry, type == VAR_TYPE_VARARGS ? -var : var);
if (name) {
int stack_idx = lua_gettop(L);
int l_type = lua_type(L, stack_idx);
if (l_type == LUA_TTABLE) {
get_table_values(res, L, stack_idx, type, depth, false, NULL);
/* depth set to 1 as 0 is taken by local variable reference */
get_table_values(res, L, stack_idx, &pi, 1, true, NULL);
}
lua_pop(L, 1);
}
}
}
}
else {
} else {
vscode_make_error_response(req, res, VSCODE_VARIABLES_RESPONSE,
"Error retrieving variables");
}
@ -823,12 +856,11 @@ static void handle_launch_request(ProtocolMessage *req, ProtocolMessage *res,
vscode_send_error_response(req, res, VSCODE_LAUNCH_RESPONSE,
"Launch failed", out, my_logger);
return;
}
else {
} else {
/* Make a note of the working directory so that we can work out the
path name of any source files */
vscode_string_copy(workingdir, req->u.Request.u.LaunchRequest.cwd,
sizeof workingdir);
sizeof workingdir);
}
}
const char *progname = req->u.Request.u.LaunchRequest.program;
@ -843,8 +875,7 @@ static void handle_launch_request(ProtocolMessage *req, ProtocolMessage *res,
"Launch failed", out, my_logger);
lua_pop(L, 1);
return;
}
else {
} else {
/* Lua program successfully compiled. Although we have not yet
launched, we tell VSCode that we have at this stage */
vscode_send_success_response(req, res, VSCODE_LAUNCH_RESPONSE, out,
@ -857,7 +888,8 @@ static void handle_launch_request(ProtocolMessage *req, ProtocolMessage *res,
/* Start the Lua code! */
/* From here on the debugger will get control inside the debugger() function
below which is setup as a Lua hook whenever Lua steps across a new line of
code. When control gets back here it means the program finished executing */
code. When control gets back here it means the program finished executing
*/
if (lua_pcall(L, 0, 0, 0)) {
char temp[1024];
snprintf(temp, sizeof temp, "Program terminated with error: %s\n",
@ -874,9 +906,11 @@ static void handle_launch_request(ProtocolMessage *req, ProtocolMessage *res,
* If called from main then debugger_state == DEBUGGER_BIRTH and ar == NULL
*/
static void debugger(lua_State *L, lua_Debug *ar, FILE *in, FILE *out) {
if (debugger_state == DEBUGGER_PROGRAM_TERMINATED) { return; }
/* If the program is running or stepping over/out
if (debugger_state == DEBUGGER_PROGRAM_TERMINATED) {
return;
}
/* If the program is running or stepping over/out
then check if we hit a breakpoint. */
if (debugger_state == DEBUGGER_PROGRAM_RUNNING ||
(debugger_state == DEBUGGER_PROGRAM_STEPPING &&
@ -888,7 +922,8 @@ static void debugger(lua_State *L, lua_Debug *ar, FILE *in, FILE *out) {
if (!breakpoints[j].source.path[0] ||
ar->currentline != breakpoints[j].line)
continue;
/* potential match of breakpoint line - we need to check the source name */
/* potential match of breakpoint line - we need to check the source name
*/
if (!initialized) initialized = lua_getinfo(L, "S", ar);
if (!initialized) break;
if (ar->source[0] == '@') {
@ -913,7 +948,8 @@ static void debugger(lua_State *L, lua_Debug *ar, FILE *in, FILE *out) {
return; /* we are deeper into the stack, so continue execution */
else if (stepping_mode == DEBUGGER_STEPPING_OUT &&
L == stepping_lua_State && ar->stacklevel >= stepping_stacklevel)
return; /* we are still in current function or deeper so continue execution */
return; /* we are still in current function or deeper so continue
execution */
/* OK so we are going to be stopping */
/* running within Lua at line change */
if (!thread_event_sent) {
@ -922,8 +958,7 @@ static void debugger(lua_State *L, lua_Debug *ar, FILE *in, FILE *out) {
vscode_send_thread_event(&res, true, out, my_logger);
/* Inform VSCode we have stopped */
vscode_send_stopped_event(&res, "entry", out, my_logger);
}
else {
} else {
/* Inform VSCode we have stopped */
vscode_send_stopped_event(&res, "step", out, my_logger);
}
@ -936,9 +971,10 @@ static void debugger(lua_State *L, lua_Debug *ar, FILE *in, FILE *out) {
/* Wait for debugger command */
bool get_command = true;
int command = VSCODE_UNKNOWN_REQUEST;
//Sleep(60 * 1000);
// Sleep(60 * 1000);
while (get_command &&
(command = vscode_get_request(in, &readbuf, &req, my_logger)) != VSCODE_EOF) {
(command = vscode_get_request(in, &readbuf, &req, my_logger)) !=
VSCODE_EOF) {
switch (command) {
case VSCODE_INITIALIZE_REQUEST: {
handle_initialize_request(&req, &res, out);
@ -1043,7 +1079,9 @@ static void debugger(lua_State *L, lua_Debug *ar, FILE *in, FILE *out) {
*/
void ravi_debughook(lua_State *L, lua_Debug *ar) {
int event = ar->event;
if (event == LUA_HOOKLINE) { debugger(L, ar, stdin, stdout); }
if (event == LUA_HOOKLINE) {
debugger(L, ar, stdin, stdout);
}
}
void ravi_debug_writestring(const char *s, size_t l) {
@ -1114,7 +1152,9 @@ int main(int argc, char **argv) {
setbuf(my_logger, NULL);
setbuf(stdout, NULL);
lua_State *L = luaL_newstate(); /* create Lua state */
if (L == NULL) { return EXIT_FAILURE; }
if (L == NULL) {
return EXIT_FAILURE;
}
/* redirect Lua's stdout and stderr */
ravi_set_writefuncs(L, ravi_debug_writestring, ravi_debug_writeline,
ravi_debug_writestringerror);

@ -111,13 +111,13 @@ int test_intpacking() {
if (i1 != i2)
return 1;
PackedInteger pi;
pi.a8 = 0xFF;
pi.b8 = 0xFF;
pi.c8 = 0xFF;
pi.d8 = 0xFF;
pi.e8 = 0xFF;
pi.f8 = 0xFF;
pi.g4 = 0x0F;
pi.x8[0] = 0xFF;
pi.x8[1] = 0xFF;
pi.x8[2] = 0xFF;
pi.x8[3] = 0xFF;
pi.x8[4] = 0xFF;
pi.depth = 0xFF;
pi.vartype = 0x0F;
int64_t i3 = vscode_pack(&pi);
d = (double) i3;
i2 = (int64_t) d;
@ -129,14 +129,14 @@ int test_intpacking() {
vscode_unpack(i3, &p2);
if (memcmp(&pi, &p2, sizeof(PackedInteger)) != 0)
return 1;
fprintf(stderr, "%x %x %x %x %x %x %x\n", p2.a8, p2.b8, p2.c8, p2.d8, p2.e8, p2.f8, p2.g4);
pi.a8 = 127;
pi.b8 = 212;
pi.c8 = 13;
pi.d8 = 55;
pi.e8 = 220;
pi.f8 = 0;
pi.g4 = 15;
fprintf(stderr, "%x %x %x %x %x %x %x\n", p2.x8[0], p2.x8[1], p2.x8[2], p2.x8[3], p2.x8[4], p2.depth, p2.vartype);
pi.x8[0] = 127;
pi.x8[1] = 212;
pi.x8[2] = 13;
pi.x8[3] = 55;
pi.x8[4] = 220;
pi.depth = 0;
pi.vartype = 15;
i3 = vscode_pack(&pi);
d = (double)i3;
i2 = (int64_t)d;
@ -144,7 +144,7 @@ int test_intpacking() {
if (i3 != i2)
return 1;
vscode_unpack(i3, &p2);
fprintf(stderr, "%u %u %u %u %u %u %u\n", p2.a8, p2.b8, p2.c8, p2.d8, p2.e8, p2.f8, p2.g4);
fprintf(stderr, "%u %u %u %u %u %u %u\n", p2.x8[0], p2.x8[1], p2.x8[2], p2.x8[3], p2.x8[4], p2.depth, p2.vartype);
if (memcmp(&pi, &p2, sizeof(PackedInteger)) != 0)
return 1;
return 0;

Loading…
Cancel
Save