diff --git a/devel/200_60.md b/devel/200_60.md new file mode 100644 index 00000000..18622912 --- /dev/null +++ b/devel/200_60.md @@ -0,0 +1,27 @@ +# [200_60] Goldfish Scheme 支持 shebang + +## 2026/04/03 在 load_file_1 中实现 shebang 跳过逻辑 + +### What +在 `load_file_1` 函数中添加 shebang 行跳过逻辑,使 Goldfish Scheme 能够正确执行以 `#!` 开头的脚本文件。 + +### Why +shebang(`#!`)是 Unix-like 系统中用于指定脚本解释器的机制。用户希望能够直接运行 Goldfish Scheme 脚本,例如: + +```scheme +#!/usr/bin/env goldfish +(display "Hello, World!") +``` + +在实现 shebang 支持之前,Goldfish 会将 `#!` 解析为注释或错误语法,导致脚本无法直接执行。 + +### How +在 `load_file_1` 函数中,加载文件内容后、解析执行前,检查文件内容是否以 `#!` 开头: + +1. 检查端口数据是否以 `#` 和 `!` 开头 +2. 如果是,则循环查找第一个换行符 `\n` +3. 找到换行符后,将端口位置设置为换行符之后的位置,跳过 shebang 行 +4. 如果没有找到换行符(文件只有 shebang 一行),则将位置设置为文件末尾 + +## 任务相关的代码文件 +- `src/s7.c` - 修改 `load_file_1` 函数,添加 shebang 跳过逻辑 diff --git a/src/s7.c b/src/s7.c index e66b87de..816d4d1b 100644 --- a/src/s7.c +++ b/src/s7.c @@ -28935,6 +28935,42 @@ static s7_pointer load_file_1(s7_scheme *sc, const char *filename) port_file_number(port) = remember_file_name(sc, (local_file_name) ? local_file_name : filename); if (local_file_name) free(local_file_name); set_loader_port(port); + if ((is_string_port(port)) && + (port_data_size(port) >= 2) && + (port_data(port)[0] == '#') && + (port_data(port)[1] == '!')) + { + uint8_t *data = port_data(port); + s7_int pos = 0; + while (pos < port_data_size(port) && data[pos] != '\n') + pos++; + if (pos < port_data_size(port)) + port_position(port) = pos + 1; + else port_position(port) = port_data_size(port); + } + else + if (is_file_port(port)) + { + int32_t c0 = fgetc(port_file(port)); + if (c0 != EOF) + { + int32_t c1 = fgetc(port_file(port)); + if ((c0 == '#') && + (c1 == '!')) + { + int32_t c; + while (((c = fgetc(port_file(port))) != EOF) && + (c != '\n')) + {} + } + else + { + if (c1 != EOF) + ungetc(c1, port_file(port)); + ungetc(c0, port_file(port)); + } + } + } push_input_port(sc, port); return(port); }