From 70ecf400dee5edfa61fbaae5e2a95a54131f7695 Mon Sep 17 00:00:00 2001 From: Da Shen Date: Fri, 3 Apr 2026 11:06:41 +0800 Subject: [PATCH 1/2] =?UTF-8?q?[200=5F60]=20Goldfish=20Scheme=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20shebang?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 load_file_1 函数中添加 shebang 行跳过逻辑, 使 Goldfish Scheme 能够正确执行以 #! 开头的脚本文件。 Co-Authored-By: Claude Opus 4.6 --- devel/200_60.md | 27 +++++++++++++++++++++++++++ src/s7.c | 15 +++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 devel/200_60.md 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..48dd5436 100644 --- a/src/s7.c +++ b/src/s7.c @@ -28935,6 +28935,21 @@ 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); + /* 跳过 shebang 行:如果文件以 #! 开头,跳过第一行 */ + 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 /* 没有换行符,文件只有 shebang 行 */ + port_position(port) = port_data_size(port); + } push_input_port(sc, port); return(port); } From 1726770c1d7bc9979f10baa5da091e6ce38858c7 Mon Sep 17 00:00:00 2001 From: wumo Date: Fri, 3 Apr 2026 14:43:23 +0800 Subject: [PATCH 2/2] wip --- src/s7.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/s7.c b/src/s7.c index 48dd5436..816d4d1b 100644 --- a/src/s7.c +++ b/src/s7.c @@ -28935,21 +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); - /* 跳过 shebang 行:如果文件以 #! 开头,跳过第一行 */ - if (is_string_port(port) && - port_data_size(port) >= 2 && - port_data(port)[0] == '#' && - port_data(port)[1] == '!') + 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)) /* 找到换行符,跳过它 */ + if (pos < port_data_size(port)) port_position(port) = pos + 1; - else /* 没有换行符,文件只有 shebang 行 */ - port_position(port) = port_data_size(port); + 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); }