improve fscript debugger

This commit is contained in:
lixianjing 2022-01-24 18:40:07 +08:00
parent b2e5adf088
commit 6f75595aa5
9 changed files with 145 additions and 39 deletions

View File

@ -1,6 +1,7 @@
# 最新动态
2022/01/24
* 完善fscript debugger
* 优化tk\_strncpy感谢智明提供补丁
* 增加slider增加修改前景色的线帽形状属性感谢智明提供补丁
* 修复demoui界面上有edit控件且控件中存在文本时切换主题会打印警告的问题感谢兆坤提供补丁

View File

@ -34,6 +34,8 @@
#define DEBUGGER_TCP_PORT 6789
#endif /*DEBUGGER_TCP_PORT*/
#define DEBUGGER_START_LINE 0xffffffff
#define DEBUGGER_DEFAULT_CODE_ID "0"
#endif /*TK_DEBUGGER_CONST_H*/

View File

@ -1,5 +1,5 @@
/**
* File: debugger.c
* File: debugger_fscript.c
* Author: AWTK Develop Team
* Brief: debugger
*
@ -30,6 +30,25 @@ typedef struct _call_stack_frame_t {
tk_object_t* locals;
} call_stack_frame_t;
int32_t debugger_fscript_get_start_line(fscript_t* fscript) {
uint32_t i = 0;
fscript_args_t* args = NULL;
fscript_func_call_t* iter = NULL;
if (fscript == NULL || fscript->first == NULL) {
return 0;
}
args = &(fscript->first->args);
for (i = 0; i < args->size; i++) {
if (args->args[i].type == VALUE_TYPE_FSCRIPT_FUNC) {
iter = value_func(args->args + i);
return iter->row;
}
}
return 0;
}
static call_stack_frame_t* call_stack_frame_create(const char* name, tk_object_t* locals) {
call_stack_frame_t* frame = TKMEM_ZALLOC(call_stack_frame_t);
return_value_if_fail(frame != NULL, NULL);
@ -120,6 +139,7 @@ static ret_t debugger_fscript_pause(debugger_t* debugger) {
ret = RET_OK;
/*停止到下一行要执行的代码*/
d->next_stop_executed_line = d->executed_lines + 1;
d->break_type = DEBUGGER_FSCRIPT_BREAK_STEP_IN;
}
ret = d->paused == TRUE ? RET_OK : RET_FAIL;
debugger_fscript_unlock(debugger);
@ -152,6 +172,7 @@ static ret_t debugger_fscript_clear_step_stops(debugger_fscript_t* d) {
d->next_stop_line = -1;
d->next_stop_executed_line = -1;
d->next_stop_call_frame_index = -1;
d->break_type = DEBUGGER_FSCRIPT_BREAK_NONE;
return RET_OK;
}
@ -166,7 +187,8 @@ static ret_t debugger_fscript_step_in(debugger_t* debugger) {
ret = RET_OK;
debugger_fscript_clear_step_stops(d);
d->next_stop_executed_line = d->executed_lines + 1;
log_debug("debugger_fscript_step_in: %d %d\n", d->executed_lines, d->next_stop_executed_line);
d->break_type = DEBUGGER_FSCRIPT_BREAK_STEP_IN;
log_debug("step_in: %d %d\n", d->executed_lines, d->next_stop_executed_line);
}
debugger_fscript_unlock(debugger);
@ -189,7 +211,9 @@ static ret_t debugger_fscript_next(debugger_t* debugger) {
debugger_fscript_clear_step_stops(d);
d->next_stop_executed_line = d->executed_lines + 1;
d->next_stop_call_frame_index = d->call_stack_frames.size;
log_debug("set step in:%d\n", d->next_stop_call_frame_index);
d->break_type = DEBUGGER_FSCRIPT_BREAK_NEXT;
log_debug("next:executed_lines=%d prev_executed_line=%d\n", d->executed_lines,
d->prev_executed_line);
}
debugger_fscript_unlock(debugger);
@ -212,7 +236,8 @@ static ret_t debugger_fscript_step_out(debugger_t* debugger) {
ret = RET_OK;
debugger_fscript_clear_step_stops(d);
d->next_stop_call_frame_index = d->call_stack_frames.size - 1;
log_debug("set step out:%d\n", d->next_stop_call_frame_index);
log_debug("step out:%d\n", d->next_stop_call_frame_index);
d->break_type = DEBUGGER_FSCRIPT_BREAK_STEP_OUT;
}
debugger_fscript_unlock(debugger);
@ -234,6 +259,7 @@ static ret_t debugger_fscript_step_over(debugger_t* debugger) {
ret = RET_OK;
debugger_fscript_clear_step_stops(d);
d->next_stop_line = d->prev_executed_line + 1;
d->break_type = DEBUGGER_FSCRIPT_BREAK_STEP_OVER;
log_debug("step over: %d %d\n", d->next_stop_line, d->prev_executed_line);
}
debugger_fscript_unlock(debugger);
@ -298,6 +324,7 @@ tk_object_t* debugger_fscript_get_self(debugger_t* debugger) {
}
tk_object_t* debugger_fscript_get_global(debugger_t* debugger) {
/*FIXME:和awflow统一处理*/
return TK_OBJECT_REF(fscript_get_global_object());
}
@ -362,7 +389,11 @@ static ret_t debugger_fscript_set_break_point(debugger_t* debugger, uint32_t lin
return_value_if_fail(d != NULL, RET_BAD_PARAMS);
if (debugger_fscript_lock(debugger) == RET_OK) {
darray_push_unique(&(d->break_points), tk_pointer_from_int(line));
if (line == DEBUGGER_START_LINE) {
d->stop_at_start_line = TRUE;
} else {
darray_push_unique(&(d->break_points), tk_pointer_from_int(line));
}
debugger_fscript_unlock(debugger);
}
@ -435,10 +466,12 @@ static ret_t debugger_fscript_exec_async(void* ctx) {
}
static ret_t debugger_fscript_wait_for_debugger(debugger_t* debugger) {
int32_t start_line = 0;
debugger_fscript_t* d = DEBUGGER_FSCRIPT(debugger);
return_value_if_fail(d != NULL, RET_BAD_PARAMS);
start_line = debugger_fscript_get_start_line(d->fscript);
return darray_push_unique(&(d->break_points), tk_pointer_from_int(0));
return darray_push_unique(&(d->break_points), tk_pointer_from_int(start_line));
}
static ret_t debugger_fscript_launch(debugger_t* debugger, const char* lang,
@ -456,6 +489,7 @@ static ret_t debugger_fscript_launch(debugger_t* debugger, const char* lang,
if (fscript->code_id == NULL) {
fscript->code_id = tk_strdup(DEBUGGER_DEFAULT_CODE_ID);
}
d->fscript = fscript;
d->code_id = tk_str_copy(d->code_id, fscript->code_id);
debugger_fscript_wait_for_debugger(debugger);
ret = async_call(debugger_fscript_exec_async, NULL, fscript);
@ -618,6 +652,11 @@ ret_t debugger_fscript_set_fscript(debugger_t* debugger, fscript_t* fscript) {
darray_clear(&(d->call_stack_frames));
debugger_fscript_enter_func(debugger, "<root>", fscript->locals);
if (d->stop_at_start_line) {
d->stop_at_start_line = FALSE;
debugger_fscript_wait_for_debugger(debugger);
}
} else {
debugger_fscript_leave_func(debugger);
fscript_set_print_func(d->fscript, NULL);
@ -634,11 +673,32 @@ static bool_t debugger_fscript_should_pause(debugger_fscript_t* d, int32_t line)
if (paused) {
log_debug("break at line:%d\n", line);
return paused;
}
if (d->next_stop_line >= 0 && line >= d->next_stop_line) {
log_debug("break for over:next_stop_line=%d line=%d\n", d->next_stop_line, line);
paused = TRUE;
switch (d->break_type) {
case DEBUGGER_FSCRIPT_BREAK_STEP_IN: {
if (d->executed_lines >= d->next_stop_executed_line) {
paused = TRUE;
}
break;
}
case DEBUGGER_FSCRIPT_BREAK_NEXT: {
if (d->executed_lines >= d->next_stop_executed_line) {
if (d->next_stop_call_frame_index >= d->call_stack_frames.size) {
paused = TRUE;
}
}
break;
}
case DEBUGGER_FSCRIPT_BREAK_STEP_OVER: {
if (line >= d->next_stop_line) {
paused = TRUE;
}
break;
}
default:
break;
}
return paused;
@ -688,27 +748,14 @@ static ret_t debugger_fscript_after_exec_func(debugger_t* debugger, int32_t line
if (debugger_fscript_lock(debugger) == RET_OK) {
bool_t paused = FALSE;
log_debug("prev_executed_line=%d line=%d executed_lines=%d \n", d->prev_executed_line, line,
d->executed_lines);
if (d->prev_executed_line != line) {
d->executed_lines++;
if (d->next_stop_executed_line >= 0) {
/*step in/next */
if (d->next_stop_call_frame_index >= 0) {
/*next*/
if (d->next_stop_call_frame_index == d->call_stack_frames.size) {
paused = d->executed_lines >= d->next_stop_executed_line;
} else {
/*skip when in sub-routine*/
log_debug("not break in sub-routine\n");
}
} else {
/*step in*/
paused = d->executed_lines >= d->next_stop_executed_line;
}
}
}
d->prev_executed_line = line;
/*step out*/
if (d->next_stop_call_frame_index == d->call_stack_frames.size) {
if (d->break_type == DEBUGGER_FSCRIPT_BREAK_STEP_OUT) {
paused = TRUE;
}

View File

@ -1,5 +1,5 @@
/**
* File: fscript_debugger_fscript.h
* File: debugger_fscript.h
* Author: AWTK Develop Team
* Brief: debugger_fscript for fscript
*
@ -29,6 +29,14 @@
BEGIN_C_DECLS
typedef enum _debugger_fscript_break_type_t {
DEBUGGER_FSCRIPT_BREAK_NONE = 0,
DEBUGGER_FSCRIPT_BREAK_NEXT,
DEBUGGER_FSCRIPT_BREAK_STEP_IN,
DEBUGGER_FSCRIPT_BREAK_STEP_OUT,
DEBUGGER_FSCRIPT_BREAK_STEP_OVER
} debugger_fscript_break_type_t;
/**
* @class debugger_fscript_t
* fscript调试器
@ -63,6 +71,9 @@ typedef struct _debugger_fscript_t {
darray_t break_points;
darray_t call_stack_frames;
bool_t code_changed;
bool_t stop_at_start_line;
int32_t stop_at_next_line;
debugger_fscript_break_type_t break_type;
} debugger_fscript_t;
/**
@ -112,6 +123,16 @@ ret_t debugger_fscript_set_var(fscript_t* fscript, const char* name, const value
ret_t debugger_fscript_exec_func(fscript_t* fscript, const char* name, fscript_func_call_t* iter,
value_t* result);
/*public for tests*/
/**
* @method debugger_fscript_get_start_line
*
* @param {fscript_t*} fscript fscript对象
*
* @return {int32_t}
*/
int32_t debugger_fscript_get_start_line(fscript_t* fscript);
END_C_DECLS
#endif /*TK_DEBUGGER_FSCRIPT_H*/

View File

@ -1757,6 +1757,9 @@ static ret_t fscript_parse_all(fscript_parser_t* parser, fscript_func_call_t* ac
ret = fscript_parse_function_def(parser, acall);
} else if (t == NULL || t->type == TOKEN_EOF) {
break;
} else if (t->type == TOKEN_RBRACKET) {
fscript_parser_set_error(parser, "unexpected token");
break;
} else {
fscript_parser_unget_token(parser);
ret = fscript_parse_statements(parser, acall);

View File

@ -1242,7 +1242,7 @@ bool_t tk_str_is_in_array(const char* str, const char** str_array, uint32_t arra
}
void* tk_memcpy_by_align_4(void* dst_align_4, const void* src_align_4, uint32_t len) {
#define MEMCPY_TINY_MAX_LENGTH 64
#define MEMCPY_TINY_MAX_LENGTH 64
if (dst_align_4 != NULL && src_align_4 != NULL && len > 0) {
if (len < MEMCPY_TINY_MAX_LENGTH) {
register unsigned char* dd = (unsigned char*)dst_align_4 + len;

View File

@ -61,6 +61,38 @@ static ret_t on_debugger_client_event(void* ctx, event_t* e) {
return RET_OK;
}
TEST(Debugger, start_line1) {
const char* code =
"//hello\n"
"function foo(a, b) {\n"
" return a + b;\n"
"}\n"
"print(foo(1, 2))\n"
"//code_id(\"85e86311e2d595c65b745d8143b6085efe819c354584742f72aeacd3336a0a5e\")";
tk_object_t* obj = object_default_create();
fscript_t* fscript = fscript_create(obj, code);
ASSERT_EQ(debugger_fscript_get_start_line(fscript), 4);
fscript_destroy(fscript);
TK_OBJECT_UNREF(obj);
}
TEST(Debugger, start_line2) {
const char* code =
"\n"
"function foo(a, b) {\n"
" return a + b;\n"
"}\n"
"print(foo(1, 2))\n"
"//code_id(\"85e86311e2d595c65b745d8143b6085efe819c354584742f72aeacd3336a0a5e\")";
tk_object_t* obj = object_default_create();
fscript_t* fscript = fscript_create(obj, code);
ASSERT_EQ(debugger_fscript_get_start_line(fscript), 4);
fscript_destroy(fscript);
TK_OBJECT_UNREF(obj);
}
TEST(Debugger, launch) {
const char* code =
"var i = 0\n"
@ -116,9 +148,9 @@ TEST(Debugger, launch) {
debugger_server_tcp_deinit();
debugger_global_deinit();
ASSERT_STREQ(str.str,
"breaked(0)breaked(1)log(2,\"0\")breaked(2)breaked(1)log(2,\"1\")breaked(2)breaked("
"1)log(2,\"2\")log(2,\"3\")log(2,\"4\")log(2,\"5\")log(2,\"6\")log(2,\"7\")log(2,"
"\"8\")log(2,\"9\")log(4,\"10\")completed()");
"breaked(0)breaked(1)log(2,\"0\")breaked(2)log(2,\"1\")breaked(1)log(2,\"2\")"
"breaked(2)log(2,\"3\")breaked(1)log(2,\"4\")log(2,\"5\")log(2,\"6\")log(2,\"7\")"
"log(2,\"8\")log(2,\"9\")log(4,\"10\")completed()");
str_reset(&str);
async_call_deinit();
}
@ -186,9 +218,9 @@ TEST(Debugger, next) {
debugger_server_tcp_deinit();
debugger_global_deinit();
ASSERT_STREQ(str.str,
"breaked(0)breaked(1)log(2,\"0\")breaked(2)breaked(1)log(2,\"1\")breaked(2)breaked("
"1)log(2,\"2\")log(2,\"3\")log(2,\"4\")log(2,\"5\")log(2,\"6\")log(2,\"7\")log(2,"
"\"8\")log(2,\"9\")log(4,\"10\")completed()");
"breaked(0)breaked(1)log(2,\"0\")breaked(2)log(2,\"1\")breaked(1)log(2,\"2\")"
"breaked(2)log(2,\"3\")breaked(1)log(2,\"4\")log(2,\"5\")log(2,\"6\")log(2,\"7\")"
"log(2,\"8\")log(2,\"9\")log(4,\"10\")completed()");
str_reset(&str);
}
@ -447,7 +479,7 @@ TEST(Debugger, step_in) {
debugger_global_deinit();
ASSERT_STREQ(
str.str,
"breaked(8)breaked(6)breaked(2)breaked(6)breaked(8)log(9,\"600.000000\")completed()");
"breaked(8)breaked(6)breaked(3)breaked(6)breaked(8)log(9,\"600.000000\")completed()");
str_reset(&str);
}

View File

@ -482,7 +482,7 @@ int main(int argc, char* argv[]) {
}
debugger_attach(client, DEBUGGER_LANG_FSCRIPT, DEBUGGER_DEFAULT_CODE_ID);
debugger_set_break_point(client, 0);
debugger_set_break_point(client, DEBUGGER_START_LINE);
aw_flow_shell_run(client);

View File

@ -591,11 +591,11 @@ TEST(Utils, memcpy_by_align_4) {
#define path_max_len 64
uint8_t path[path_max_len * 2] = {0};
uint8_t path1[path_max_len * 2] = {0};
for (uint8_t i = 0; i < path_max_len * 2; i++) {
path1[i] = i;
}
tk_memcpy_by_align_4(path, path1, path_max_len);
for (uint8_t i = 0; i < path_max_len; i++) {
@ -623,7 +623,7 @@ TEST(Utils, tk_memcpy) {
for (uint8_t i = 0; i < path_max_len * 2; i++) {
path1[i] = i;
}
tk_memcpy(path, path1, path_max_len);
for (uint8_t i = 0; i < path_max_len; i++) {