mirror of
https://github.com/fluencelabs/redis
synced 2025-03-19 17:10:50 +00:00
Lua debugger: breakpoints.
This commit is contained in:
parent
5c4f492844
commit
1f8d614423
@ -490,6 +490,51 @@ static sds cliFormatReplyTTY(redisReply *r, char *prefix) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int isColorTerm(void) {
|
||||||
|
char *t = getenv("TERM");
|
||||||
|
return t != NULL && strstr(t,"xterm") != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helpe function for sdsCatColorizedLdbReply() appending colorize strings
|
||||||
|
* to an SDS string. */
|
||||||
|
sds sdscatcolor(sds o, char *s, size_t len, char *color) {
|
||||||
|
if (!isColorTerm()) return sdscatlen(o,s,len);
|
||||||
|
|
||||||
|
int bold = strstr(color,"bold") != NULL;
|
||||||
|
int ccode = 37; /* Defaults to white. */
|
||||||
|
if (strstr(color,"red")) ccode = 31;
|
||||||
|
else if (strstr(color,"red")) ccode = 31;
|
||||||
|
else if (strstr(color,"green")) ccode = 32;
|
||||||
|
else if (strstr(color,"yellow")) ccode = 33;
|
||||||
|
else if (strstr(color,"blue")) ccode = 34;
|
||||||
|
else if (strstr(color,"magenta")) ccode = 35;
|
||||||
|
else if (strstr(color,"cyan")) ccode = 36;
|
||||||
|
else if (strstr(color,"white")) ccode = 37;
|
||||||
|
|
||||||
|
o = sdscatfmt(o,"\033[%i;%i;49m",bold,ccode);
|
||||||
|
o = sdscatlen(o,s,len);
|
||||||
|
o = sdscat(o,"\033[0m");
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Colorize Lua debugger status replies according to the prefix they
|
||||||
|
* have. */
|
||||||
|
sds sdsCatColorizedLdbReply(sds o, char *s, size_t len) {
|
||||||
|
char *color = "white";
|
||||||
|
|
||||||
|
if (strstr(s,"<redis>")) color = "green";
|
||||||
|
if (strstr(s,"<reply>")) color = "cyan";
|
||||||
|
if (strstr(s,"<error>")) color = "red";
|
||||||
|
if (strstr(s,"<value>")) color = "magenta";
|
||||||
|
if (isdigit(s[0])) {
|
||||||
|
char *p = s+1;
|
||||||
|
while(isdigit(*p)) p++;
|
||||||
|
if (*p == '*') color = "yellow"; /* Current line. */
|
||||||
|
else if (*p == '#') color = "bold"; /* Break point. */
|
||||||
|
}
|
||||||
|
return sdscatcolor(o,s,len,color);
|
||||||
|
}
|
||||||
|
|
||||||
static sds cliFormatReplyRaw(redisReply *r) {
|
static sds cliFormatReplyRaw(redisReply *r) {
|
||||||
sds out = sdsempty(), tmp;
|
sds out = sdsempty(), tmp;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -504,7 +549,14 @@ static sds cliFormatReplyRaw(redisReply *r) {
|
|||||||
break;
|
break;
|
||||||
case REDIS_REPLY_STATUS:
|
case REDIS_REPLY_STATUS:
|
||||||
case REDIS_REPLY_STRING:
|
case REDIS_REPLY_STRING:
|
||||||
out = sdscatlen(out,r->str,r->len);
|
if (r->type == REDIS_REPLY_STATUS && config.eval_ldb) {
|
||||||
|
/* The Lua debugger replies with arrays of simple (status)
|
||||||
|
* strings. We colorize the output for more fun if this
|
||||||
|
* is a debugging session. */
|
||||||
|
out = sdsCatColorizedLdbReply(out,r->str,r->len);
|
||||||
|
} else {
|
||||||
|
out = sdscatlen(out,r->str,r->len);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case REDIS_REPLY_INTEGER:
|
case REDIS_REPLY_INTEGER:
|
||||||
out = sdscatprintf(out,"%lld",r->integer);
|
out = sdscatprintf(out,"%lld",r->integer);
|
||||||
|
106
src/scripting.c
106
src/scripting.c
@ -1602,8 +1602,39 @@ char *ldbGetSourceLine(int line) {
|
|||||||
return ldb.src[idx];
|
return ldb.src[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if there is a breakpoint in the specified line. */
|
||||||
int ldbIsBreakpoint(int line) {
|
int ldbIsBreakpoint(int line) {
|
||||||
/* TODO: fixme. */
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < ldb.bpcount; j++)
|
||||||
|
if (ldb.bp[j] == line) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the specified breakpoint. Ignore it if we already reached the max.
|
||||||
|
* Returns 1 if the breakpoint was added (or was already set). 0 if there is
|
||||||
|
* no space for the breakpoint or if the line is invalid. */
|
||||||
|
int ldbAddBreakpoint(int line) {
|
||||||
|
if (line <= 0 || line > ldb.lines) return 0;
|
||||||
|
if (!ldbIsBreakpoint(line) && ldb.bpcount != LDB_BREAKPOINTS_MAX) {
|
||||||
|
ldb.bp[ldb.bpcount++] = line;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the specified breakpoint, returning 1 if the operation was
|
||||||
|
* performed or 0 if there was no such breakpoint. */
|
||||||
|
int ldbDelBreakpoint(int line) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < ldb.bpcount; j++) {
|
||||||
|
if (ldb.bp[j] == line) {
|
||||||
|
ldb.bpcount--;
|
||||||
|
memmove(ldb.bp+j,ldb.bp+j+1,ldb.bpcount-j);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1668,10 +1699,10 @@ void ldbList(int around, int context) {
|
|||||||
if (around != 0 && abs(around-j) > context) continue;
|
if (around != 0 && abs(around-j) > context) continue;
|
||||||
char *line = ldbGetSourceLine(j);
|
char *line = ldbGetSourceLine(j);
|
||||||
int mark;
|
int mark;
|
||||||
if (ldbIsBreakpoint(j))
|
if (ldb.currentline == j)
|
||||||
mark = '#';
|
mark = '*';
|
||||||
else
|
else
|
||||||
mark = (ldb.currentline == j) ? '*' : ':';
|
mark = ldbIsBreakpoint(j) ? '#' : ':';
|
||||||
sds thisline = sdscatprintf(sdsempty(),"%d%c %s", j, mark, line);
|
sds thisline = sdscatprintf(sdsempty(),"%d%c %s", j, mark, line);
|
||||||
ldbLog(thisline);
|
ldbLog(thisline);
|
||||||
}
|
}
|
||||||
@ -1723,8 +1754,9 @@ void ldbLogStackValue(lua_State *lua) {
|
|||||||
/* Implements the "print" command of the Lua debugger. It scans for Lua
|
/* Implements the "print" command of the Lua debugger. It scans for Lua
|
||||||
* var "varname" starting from the current stack frame up to the top stack
|
* var "varname" starting from the current stack frame up to the top stack
|
||||||
* frame. The first matching variable is printed. */
|
* frame. The first matching variable is printed. */
|
||||||
void ldbPrint(lua_State *lua, lua_Debug *orig_ar, char *varname) {
|
void ldbPrint(lua_State *lua, char *varname) {
|
||||||
lua_Debug ar;
|
lua_Debug ar;
|
||||||
|
|
||||||
int l = 0; /* Stack level. */
|
int l = 0; /* Stack level. */
|
||||||
while (lua_getstack(lua,l,&ar) != 0) {
|
while (lua_getstack(lua,l,&ar) != 0) {
|
||||||
l++;
|
l++;
|
||||||
@ -1743,8 +1775,52 @@ void ldbPrint(lua_State *lua, lua_Debug *orig_ar, char *varname) {
|
|||||||
ldbLog(sdsnew("No such variable."));
|
ldbLog(sdsnew("No such variable."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implements the break command to list, add and remove breakpoints. */
|
||||||
|
void ldbBreak(sds *argv, int argc) {
|
||||||
|
if (argc == 1) {
|
||||||
|
if (ldb.bpcount == 0) {
|
||||||
|
ldbLog(sdsnew("No breakpoints set. Use 'b <line>' to add one."));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ldbLog(sdscatfmt(sdsempty(),"%i breakpoints set:",ldb.bpcount));
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < ldb.bpcount; j++) {
|
||||||
|
ldbLog(sdscatfmt(sdsempty(),"%i# %s", ldb.bp[j],
|
||||||
|
ldbGetSourceLine(ldb.bp[j])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int j;
|
||||||
|
for (j = 1; j < argc; j++) {
|
||||||
|
char *arg = argv[j];
|
||||||
|
long line;
|
||||||
|
if (!string2l(arg,sdslen(arg),&line)) {
|
||||||
|
ldbLog(sdscatfmt(sdsempty(),"Invalid argument:'%s'",arg));
|
||||||
|
} else {
|
||||||
|
if (line == 0) {
|
||||||
|
ldb.bpcount = 0;
|
||||||
|
ldbLog(sdsnew("All breakpoints removed."));
|
||||||
|
} else if (line > 0) {
|
||||||
|
if (ldb.bpcount == LDB_BREAKPOINTS_MAX) {
|
||||||
|
ldbLog(sdsnew("Too many breakpoints set."));
|
||||||
|
} else if (ldbAddBreakpoint(line)) {
|
||||||
|
ldbList(line,1);
|
||||||
|
} else {
|
||||||
|
ldbLog(sdsnew("Wrong line number."));
|
||||||
|
}
|
||||||
|
} else if (line < 0) {
|
||||||
|
if (ldbDelBreakpoint(line))
|
||||||
|
ldbLog(sdsnew("Breakpoint removed."));
|
||||||
|
else
|
||||||
|
ldbLog(sdsnew("No breakpoint in the specified line."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Read debugging commands from client. */
|
/* Read debugging commands from client. */
|
||||||
void ldbRepl(lua_State *lua, lua_Debug *ar) {
|
void ldbRepl(lua_State *lua) {
|
||||||
sds *argv;
|
sds *argv;
|
||||||
int argc;
|
int argc;
|
||||||
|
|
||||||
@ -1777,6 +1853,10 @@ ldbLog(sdsnew("[c]continue Run till next breakpoint."));
|
|||||||
ldbLog(sdsnew("[l]list [line] List source code, around [line] if specified"));
|
ldbLog(sdsnew("[l]list [line] List source code, around [line] if specified"));
|
||||||
ldbLog(sdsnew(" you can use another arg for context size."));
|
ldbLog(sdsnew(" you can use another arg for context size."));
|
||||||
ldbLog(sdsnew("[p]rint <var> Show the value of the specified local variable."));
|
ldbLog(sdsnew("[p]rint <var> Show the value of the specified local variable."));
|
||||||
|
ldbLog(sdsnew("[b]eark Show all breakpoints."));
|
||||||
|
ldbLog(sdsnew("[b]eark <line> Add a breakpoint to the specified line."));
|
||||||
|
ldbLog(sdsnew("[b]eark -<line> Remove breakpoint from the specified line."));
|
||||||
|
ldbLog(sdsnew("[b]eark 0 Remove all breakpoints."));
|
||||||
ldbSendLogs();
|
ldbSendLogs();
|
||||||
} else if (!strcasecmp(argv[0],"s") || !strcasecmp(argv[0],"step") ||
|
} else if (!strcasecmp(argv[0],"s") || !strcasecmp(argv[0],"step") ||
|
||||||
!strcasecmp(argv[0],"n") || !strcasecmp(argv[0],"next")) {
|
!strcasecmp(argv[0],"n") || !strcasecmp(argv[0],"next")) {
|
||||||
@ -1784,10 +1864,13 @@ ldbLog(sdsnew("[p]rint <var> Show the value of the specified local variable.")
|
|||||||
break;
|
break;
|
||||||
} else if (!strcasecmp(argv[0],"c") || !strcasecmp(argv[0],"continue")){
|
} else if (!strcasecmp(argv[0],"c") || !strcasecmp(argv[0],"continue")){
|
||||||
break;
|
break;
|
||||||
|
} else if (!strcasecmp(argv[0],"b") || !strcasecmp(argv[0],"break")){
|
||||||
|
ldbBreak(argv,argc);
|
||||||
|
ldbSendLogs();
|
||||||
} else if (argc == 2 &&
|
} else if (argc == 2 &&
|
||||||
(!strcasecmp(argv[0],"p") || !strcasecmp(argv[0],"print")))
|
(!strcasecmp(argv[0],"p") || !strcasecmp(argv[0],"print")))
|
||||||
{
|
{
|
||||||
ldbPrint(lua,ar,argv[1]);
|
ldbPrint(lua,argv[1]);
|
||||||
ldbSendLogs();
|
ldbSendLogs();
|
||||||
} else if (!strcasecmp(argv[0],"l") || !strcasecmp(argv[0],"list")){
|
} else if (!strcasecmp(argv[0],"l") || !strcasecmp(argv[0],"list")){
|
||||||
int around = 0, ctx = 5;
|
int around = 0, ctx = 5;
|
||||||
@ -1816,13 +1899,14 @@ void luaLdbLineHook(lua_State *lua, lua_Debug *ar) {
|
|||||||
lua_getinfo(lua,"Sl",ar);
|
lua_getinfo(lua,"Sl",ar);
|
||||||
if(strstr(ar->short_src,"user_script") == NULL) return;
|
if(strstr(ar->short_src,"user_script") == NULL) return;
|
||||||
|
|
||||||
if (ldb.step) {
|
if (ldb.step || ldbIsBreakpoint(ar->currentline)) {
|
||||||
ldb.currentline = ar->currentline;
|
ldb.currentline = ar->currentline;
|
||||||
ldb.step = 0;
|
ldb.step = 0;
|
||||||
ldbLog(sdscatprintf(sdsempty(),"%d: %s", (int)ar->currentline,
|
int mark = ldbIsBreakpoint(ldb.currentline) ? '#' : '*';
|
||||||
ldbGetSourceLine(ar->currentline)));
|
ldbLog(sdscatprintf(sdsempty(),"%d%c %s", (int)ar->currentline,
|
||||||
|
mark, ldbGetSourceLine(ar->currentline)));
|
||||||
ldbSendLogs();
|
ldbSendLogs();
|
||||||
ldbRepl(lua,ar);
|
ldbRepl(lua);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user