问题
原版的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 loopif (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");}//stdinfor (;;) {...}
}
新增一个main函数
int main(int argc, char** argv) {if (argc > 1) {return main_(argc, argv);//debug release都支持带参数执行}else {
#ifdef DEBUGchar* argv_test[2] = { "./minilisp" ,"(+ 1 2)" };//debug时,支持单步调试
#elsechar* argv_test[1] = { "./minilisp" };//release时,等于原版
#endif // DEBUGreturn main_(sizeof(argv_test) / sizeof(char*), argv_test);}
}
debug release测试效果
单步debug效果
图中515这一行的原始代码是int c = getchar();
原版的会卡在getchar()这一行,执行不下去
程序会等待控制台输入一个字符
以上或许是一种c程序的改造范式,可复用。
这让我想起了,将exe改为dll,将dll改为exe,也是类似变更入口函数即可。