问题
原版的minilisp编译器不支持argv输入测试,不方便单步调试。
代码改造目标是既不改变原有程序的各种功能,
又能支持个人习惯的vs单步debug模式。
CMakeLists.txt变更
定义DEBUG宏
解决单步调试源码定位偏差问题
cmake_minimum_required(VERSION 3.10)
project(minilisp)
add_compile_options(-std=gnu99 -g -Wall)
# Create executable
add_executable(minilisp minilisp.c)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(minilisp PRIVATE -O0)
target_compile_options(minilisp PRIVATE -DDEBUG)
else()
target_compile_options(minilisp PRIVATE -O2)
endif()
源码变更
加两个变量
static char* g_arg = NULL;
static int g_pos = 0;
加两个函数my_getchar my_ungetc
将代码中getchar()替换为my_getchar()
ungetc(c, stream)替换为my_ungetc(c, stream)
static int my_getchar() {
if (NULL == g_arg) {
return getchar();
}
else {
if (0 != g_arg[g_pos]) {
return g_arg[g_pos++];
}
else {
return EOF;
}
}
}
static void my_ungetc(int c, FILE* stream) {
if (NULL == g_arg) {
ungetc(c, stream);
}
else {
if (g_pos > 0) {
--g_pos;
}
}
}
修改main函数
原版main函数改为main_函数
并在main_中加入以下判断
int main_(int argc, char** argv) {
...
// The main loop
if (argc > 1) {
//argv[1]
printf("run by arg : %s\n", argv[1]);
g_arg = argv[1];
g_pos = 0;
}
else {
printf("run by user input, eg:(+ 2 3)\n");
}
//stdin
for (;;) {
...
}
}
新增一个main函数
int main(int argc, char** argv) {
if (argc > 1) {
return main_(argc, argv);//debug release都支持带参数执行
}
else {
#ifdef DEBUG
char* argv_test[2] = { "./minilisp" ,"(+ 1 2)" };//debug时,支持单步调试
#else
char* argv_test[1] = { "./minilisp" };//release时,等于原版
#endif // DEBUG
return main_(sizeof(argv_test) / sizeof(char*), argv_test);
}
}
debug release测试效果
单步debug效果
图中515这一行的原始代码是int c = getchar();
原版的会卡在getchar()这一行,执行不下去
程序会等待控制台输入一个字符
以上或许是一种c程序的改造范式,可复用。
这让我想起了,将exe改为dll,将dll改为exe,也是类似变更入口函数即可。