issue #82 debugger code cleanup and start table expansion implementation

pull/85/head
Dibyendu Majumdar 8 years ago
parent e26d1df3cd
commit 8c9580e322

@ -77,11 +77,13 @@ typedef struct
static void * default_alloc (size_t size, int zero, void * user_data)
{
(void) user_data;
return zero ? calloc (1, size) : malloc (size);
}
static void default_free (void * ptr, void * user_data)
{
(void) user_data;
free (ptr);
}

@ -112,14 +112,14 @@ typedef struct _json_value
struct
{
unsigned int length;
int length;
json_char * ptr; /* null terminated */
} string;
struct
{
unsigned int length;
int length;
json_object_entry * values;
@ -136,7 +136,7 @@ typedef struct _json_value
struct
{
unsigned int length;
int length;
struct _json_value ** values;
#if defined(__cplusplus) && __cplusplus >= 201103L

@ -42,6 +42,7 @@ static int vscode_message_type(json_value *js, FILE *log) {
static const char *get_string_value(json_value *js, const char *key,
FILE *log) {
(void)log;
if (js->type != json_object) { return NULL; }
for (int i = 0; i < js->u.object.length; i++) {
json_object_entry *value = &js->u.object.values[i];
@ -59,6 +60,7 @@ static const char *get_string_value(json_value *js, const char *key,
static int get_int_value(json_value *js, const char *key, FILE *log,
int *found) {
(void)log;
*found = 0;
if (js->type != json_object) { return 0; }
for (int i = 0; i < js->u.object.length; i++) {
@ -78,6 +80,7 @@ static int get_int_value(json_value *js, const char *key, FILE *log,
static int get_boolean_value(json_value *js, const char *key, FILE *log,
int *found) {
(void)log;
*found = 0;
if (js->type != json_object) { return 0; }
for (int i = 0; i < js->u.object.length; i++) {
@ -97,6 +100,7 @@ static int get_boolean_value(json_value *js, const char *key, FILE *log,
static json_value *get_object_value(json_value *js, const char *key,
FILE *log) {
(void)log;
if (js->type != json_object) { return NULL; }
for (int i = 0; i < js->u.object.length; i++) {
json_object_entry *value = &js->u.object.values[i];
@ -112,6 +116,7 @@ static json_value *get_object_value(json_value *js, const char *key,
static json_value *get_array_value(json_value *js, const char *key,
FILE *log) {
(void)log;
if (js->type != json_object) { return NULL; }
for (int i = 0; i < js->u.object.length; i++) {
json_object_entry *value = &js->u.object.values[i];
@ -125,14 +130,16 @@ static json_value *get_array_value(json_value *js, const char *key,
return NULL;
}
#if 0
static void dump_keys(json_value *js, FILE *log) {
(void)log;
if (js->type != json_object) return;
for (int i = 0; i < js->u.object.length; i++) {
json_object_entry *value = &js->u.object.values[i];
fprintf(log, "key '%s'\n", value->name);
}
}
#endif
typedef struct {
const char *cmdname;
@ -529,8 +536,9 @@ void vscode_serialize_response(char *buf, size_t buflen, ProtocolMessage *res) {
cp = temp + strlen(temp);
}
snprintf(cp, sizeof temp - strlen(temp),
"{\"name\":\"%s\",\"variablesReference\":0,\"value\":\"%s\"}",
"{\"name\":\"%s\",\"variablesReference\":%d,\"value\":\"%s\"}",
res->u.Response.u.VariablesResponse.variables[d].name,
res->u.Response.u.VariablesResponse.variables[d].variablesReference,
res->u.Response.u.VariablesResponse.variables[d].value);
cp = temp + strlen(temp);
}
@ -616,7 +624,7 @@ void vscode_send(ProtocolMessage *msg, FILE *out, FILE *log) {
else
return;
fprintf(log, "%s\n", buf);
fprintf(out, buf);
fprintf(out, "%s", buf);
}
/*
@ -686,7 +694,7 @@ int vscode_get_request(FILE *in, ProtocolMessage *req, FILE *log) {
bufp += 16;
/* get the message length */
int len = atoi(bufp);
if (len >= sizeof buf) {
if (len >= (int)(sizeof buf)) {
/* FIXME */
fprintf(log,
"FATAL ERROR - Content-Length = %d is greater than bufsize\n",

@ -3,6 +3,7 @@
* a debugger in the VSCode IDE.
*/
#include <assert.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@ -30,11 +31,32 @@ enum {
DEBUGGER_PROGRAM_TERMINATED = 7
};
enum {
VAR_TYPE_LOCALS = 1,
VAR_TYPE_UPVALUES = 2,
VAR_TYPE_GLOBALS = 3
};
#define MASK0 0x3F
#define MASK 0xFF
#define MASK1 0x3
#define MAKENUM(t,a,b,c,d) \
(( ((t)&MASK1) | (((a)&MASK0) << 2) ) | \
( ((b)&MASK) << 8 ) | \
( ((c)&MASK) << 16 ) | \
( ((d)&MASK) << 24 ))
#define EXTRACT_T(x) ( (x)&MASK1 )
#define EXTRACT_A(x) ( ((x)>>2) & MASK0 )
#define EXTRACT_B(x) ( ((x)>>8) & MASK )
#define EXTRACT_C(x) ( ((x)>>16) & MASK )
#define EXTRACT_D(x) ( ((x)>>24) & MASK )
static FILE *log = NULL;
static int thread_event_sent = 0;
static int debugger_state = DEBUGGER_BIRTH;
static Breakpoint breakpoints[20];
static int num_breakpoints;
/*
* Generate response to InitializeRequest
@ -42,7 +64,6 @@ static int num_breakpoints;
*/
static void handle_initialize_request(ProtocolMessage *req,
ProtocolMessage *res, FILE *out) {
char buf[1024];
if (debugger_state >= DEBUGGER_INITIALIZED) {
vscode_send_error_response(req, res, VSCODE_INITIALIZE_RESPONSE,
"already initialized", out, log);
@ -81,7 +102,6 @@ static void handle_thread_request(ProtocolMessage *req, ProtocolMessage *res,
static void handle_stack_trace_request(ProtocolMessage *req,
ProtocolMessage *res, lua_State *L,
FILE *out) {
char buf[1024];
lua_Debug entry;
int depth = 0;
vscode_make_success_response(req, res, VSCODE_STACK_TRACE_RESPONSE);
@ -162,7 +182,6 @@ static void handle_set_breakpoints_request(ProtocolMessage *req,
*/
static void handle_scopes_request(ProtocolMessage *req, ProtocolMessage *res,
lua_State *L, FILE *out) {
char buf[1024];
lua_Debug entry;
int depth = 0;
vscode_make_success_response(req, res, VSCODE_SCOPES_RESPONSE);
@ -173,20 +192,17 @@ static void handle_scopes_request(ProtocolMessage *req, ProtocolMessage *res,
int i = 0;
strncpy(res->u.Response.u.ScopesResponse.scopes[i].name, "Locals",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
res->u.Response.u.ScopesResponse.scopes[i].variablesReference =
1000000 + depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference = MAKENUM(VAR_TYPE_LOCALS, depth, 0, 0, 0);
res->u.Response.u.ScopesResponse.scopes[i++].expensive = 0;
if (entry.nups > 0) {
strncpy(res->u.Response.u.ScopesResponse.scopes[i].name, "Up Values",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
res->u.Response.u.ScopesResponse.scopes[i].variablesReference =
2000000 + depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference = MAKENUM(VAR_TYPE_UPVALUES, depth, 0, 0, 0);
res->u.Response.u.ScopesResponse.scopes[i++].expensive = 0;
}
strncpy(res->u.Response.u.ScopesResponse.scopes[i].name, "Globals",
sizeof res->u.Response.u.ScopesResponse.scopes[0].name);
res->u.Response.u.ScopesResponse.scopes[i].variablesReference =
3000000 + depth;
res->u.Response.u.ScopesResponse.scopes[i].variablesReference = MAKENUM(VAR_TYPE_GLOBALS, depth, 0, 0, 0);
res->u.Response.u.ScopesResponse.scopes[i].expensive = 1;
}
else {
@ -207,7 +223,7 @@ static void get_userdata(lua_State *L, int stack_idx, char *buf, size_t len) {
snprintf(buf, len, "%p", udata);
}
static void get_value(lua_State *L, int stack_idx, char *buf, size_t len) {
static int get_value(lua_State *L, int stack_idx, char *buf, size_t len) {
int l_type = lua_type(L, stack_idx);
*buf = 0;
switch (l_type) {
@ -239,7 +255,7 @@ static void get_value(lua_State *L, int stack_idx, char *buf, size_t len) {
}
case LUA_TTABLE: {
get_table_info(L, stack_idx, buf, len);
break;
return 1;
}
case LUA_TFUNCTION: {
snprintf(buf, len, "%p", lua_topointer(L, stack_idx));
@ -254,6 +270,7 @@ static void get_value(lua_State *L, int stack_idx, char *buf, size_t len) {
break;
}
}
return 0;
}
/*
@ -264,41 +281,40 @@ static void handle_variables_request(ProtocolMessage *req, ProtocolMessage *res,
lua_Debug entry;
vscode_make_success_response(req, res, VSCODE_VARIABLES_RESPONSE);
int varRef = req->u.Request.u.VariablesRequest.variablesReference;
int depth = 0;
char type = 0;
if (varRef >= 3000000) {
type = 'g';
depth = varRef - 3000000;
}
else if (varRef >= 2000000) {
type = 'u';
depth = varRef - 2000000;
}
else {
type = 'l';
depth = varRef - 1000000;
}
int type = EXTRACT_T(varRef);
int depth = EXTRACT_A(varRef);
int var = EXTRACT_B(varRef);
if (lua_getstack(L, depth, &entry)) {
if (type == 'l') {
for (int n = 1, v = 0; v <= MAX_VARIABLES; n++) {
const char *name = lua_getlocal(L, &entry, n);
if (name) {
if (*name != '(') {
strncpy(
res->u.Response.u.VariablesResponse.variables[v].name, name,
sizeof res->u.Response.u.VariablesResponse.variables[0].name);
get_value(
L, lua_gettop(L),
res->u.Response.u.VariablesResponse.variables[v].value,
sizeof res->u.Response.u.VariablesResponse.variables[0].value);
v++;
if (type == VAR_TYPE_LOCALS) { // locals
if (var == 0) {
for (int n = 1, v = 0; v <= MAX_VARIABLES; n++) {
const char *name = lua_getlocal(L, &entry, n);
if (name) {
if (*name != '(') {
strncpy(
res->u.Response.u.VariablesResponse.variables[v].name, name,
sizeof res->u.Response.u.VariablesResponse.variables[0].name);
var = get_value(
L, lua_gettop(L),
res->u.Response.u.VariablesResponse.variables[v].value,
sizeof res->u.Response.u.VariablesResponse.variables[0].value);
/* If the variable has a structure then we pass pack a reference
that is used by the front end to drill down */
res->u.Response.u.VariablesResponse.variables[v].variablesReference = var ?
MAKENUM(type, depth, n, 0, 0) : 0;
v++;
}
lua_pop(L, 1); /* pop the value */
}
else {
break;
}
lua_pop(L, 1); /* pop the value */
}
else {
break;
}
}
else {
/* TODO extract variable */
fprintf(log, "\n--> Request to extract local variable %d of type %d at depth %d\n", var, type, depth);
}
}
}
else {
@ -349,9 +365,8 @@ static void handle_launch_request(ProtocolMessage *req, ProtocolMessage *res,
* Called via Lua Hook or via main
* If called from main then init is true and ar == NULL
*/
static void debugger(lua_State *L, bool init, lua_Debug *ar, FILE *in,
static void debugger(lua_State *L, lua_Debug *ar, FILE *in,
FILE *out) {
char buf[4096] = {0};
ProtocolMessage req, res;
if (debugger_state == DEBUGGER_PROGRAM_TERMINATED) {
return;
@ -484,7 +499,7 @@ static void debugger(lua_State *L, bool init, lua_Debug *ar, FILE *in,
*/
void ravi_debughook(lua_State *L, lua_Debug *ar) {
int event = ar->event;
if (event == LUA_HOOKLINE) { debugger(L, false, ar, stdin, stdout); }
if (event == LUA_HOOKLINE) { debugger(L, ar, stdin, stdout); }
}
/*
@ -492,9 +507,14 @@ void ravi_debughook(lua_State *L, lua_Debug *ar) {
* The debugger will use stdin/stdout to interact with VSCode
* The protocol used is described in protocol.h.
*/
int main(int argc, const char *argv[]) {
log = stderr; //fopen("\\temp\\out1.txt", "w");
if (log == NULL) exit(1);
int main(void) {
#ifdef _WIN32
log = fopen("/temp/out1.txt", "w");
#else
log = fopen("/tmp/out1.txt", "w");
#endif
if (log == NULL)
log = stderr;
#ifdef _WIN32
/* The VSCode debug protocol requires binary IO */
_setmode(_fileno(stdout), _O_BINARY);
@ -509,7 +529,7 @@ int main(int argc, const char *argv[]) {
luaL_openlibs(L); /* open standard libraries */
lua_sethook(L, ravi_debughook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
debugger_state = DEBUGGER_BIRTH;
debugger(L, true, NULL, stdin, stdout);
debugger(L, NULL, stdin, stdout);
lua_close(L);
fclose(log);
return 0;

@ -27,7 +27,7 @@ int test_initreq() {
"unable to initialize");
char buf[1024];
vscode_serialize_response(buf, sizeof buf, &res);
printf(buf);
//printf(buf);
const char *expected =
"Content-Length: "
"115\r\n\r\n{\"type\":\"response\",\"seq\":1,\"command\":\"initialize\",\"request_seq\":1,"
@ -57,10 +57,38 @@ int test_initreq() {
return 0;
}
int main(int argc, const char *argv[]) {
void experiment() {
uint32_t i = 0;
uint32_t MASK0 = 0x7F;
uint32_t MASK = 0xFF;
uint32_t MASK1 = 0x1;
#define MAKENUM(t,a,b,c,d) \
( ((t)&MASK1) | (((a)&MASK0) << 1) ) | \
( ((b)&MASK) << 8 ) | \
( ((c)&MASK) << 16 ) | \
( ((d)&MASK) << 24 )
i = MAKENUM(1, 1, 1, 1, 1);
printf("NUM = %d\n", i);
#define EXTRACT_T(x) ( (x)&MASK1 )
#define EXTRACT_A(x) ( ((x)>>1) & MASK0 )
#define EXTRACT_B(x) ( ((x)>>8) & MASK )
#define EXTRACT_C(x) ( ((x)>>16) & MASK )
#define EXTRACT_D(x) ( ((x)>>24) & MASK )
printf("%d,%d,%d,%d,%d\n", EXTRACT_T(i), EXTRACT_A(i), EXTRACT_B(i),
EXTRACT_C(i), EXTRACT_D(i));
}
int main(void) {
setbuf(stdout, NULL);
int rc = 0;
rc += test_initreq();
experiment();
if (rc == 0) printf("OK\n");
return rc == 0 ? 0 : 1;
}

Loading…
Cancel
Save