Skip to content

[200_60] Goldfish Scheme 支持忽略 shebang#652

Merged
da-liii merged 2 commits intomainfrom
da/200_60/shabang
Apr 3, 2026
Merged

[200_60] Goldfish Scheme 支持忽略 shebang#652
da-liii merged 2 commits intomainfrom
da/200_60/shabang

Conversation

@da-liii
Copy link
Copy Markdown
Contributor

@da-liii da-liii commented Apr 3, 2026

功能描述

load_file_1 函数中添加 shebang 行跳过逻辑,使 Goldfish Scheme 能够正确执行以 #! 开头的脚本文件。

实现细节

  • 在加载文件内容后、解析执行前,检查文件内容是否以 #! 开头
  • 如果是,则跳过第一行(shebang 行)
  • 处理有换行符和无换行符的情况

使用示例

用户现在可以创建如下脚本并直接执行:

#!/usr/bin/env goldfish
(display "Hello, World!")

相关文档

  • devel/200_60.md - 任务详细说明

🤖 Generated with Claude Code

在 load_file_1 函数中添加 shebang 行跳过逻辑,
使 Goldfish Scheme 能够正确执行以 #! 开头的脚本文件。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@da-liii da-liii changed the title [200_60] Goldfish Scheme 支持 shebang [200_60] Goldfish Scheme 支持忽略 shebang Apr 3, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 3, 2026

Greptile Summary

This PR adds shebang (#!) support to Goldfish Scheme by modifying load_file_1 in src/s7.c, allowing scripts that start with #!/usr/bin/env goldfish to be executed directly on Unix-like systems.

  • The implementation checks whether the loaded port is a string_port with data beginning with #!, then advances the read position past the first line before parsing begins.
  • The logic is correct and safe on non-Windows platforms for normal files: read_file always creates a string_port when loading via load_file_1 (which passes max_size = -1).
  • Windows gap: On Windows, read_file unconditionally creates a file_port (the #else branch sets port_data = NULL). The is_string_port guard prevents a crash, but the shebang line is never skipped, so shebang scripts will fail to parse on Windows without any error message explaining why.
  • No automated test cases were added for the shebang feature. Per the project's TDD guidelines in CLAUDE.md, tests should accompany new functionality.

Confidence Score: 3/5

Safe to merge for Unix-like platforms; Windows shebang support is silently broken and no tests were added.

The core logic is correct and non-crashing on all platforms (the is_string_port guard prevents NULL dereference on Windows/pseudo-files). However, the feature silently does nothing on Windows, and there are no test cases to verify correct behavior or catch regressions — both gaps that should be addressed before or shortly after merging.

src/s7.c — specifically the Windows file_port path that is unhandled by the new shebang logic.

Important Files Changed

Filename Overview
src/s7.c Adds shebang-skip logic inside load_file_1; correct for the common (non-Windows) string-port path, but silently ineffective on Windows where the port is always a file_port.
devel/200_60.md New task documentation file; accurately describes the What/Why/How of the shebang implementation. No code issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[load_file_1 called] --> B[fopen file]
    B --> C{fp valid?}
    C -- No --> Z[return NULL]
    C -- Yes --> D["read_file(sc, fp, name, -1, 'load')"]
    D --> E{Platform?}
    E -- "Windows (#else)" --> F["port_type = file_port\nport_data = NULL"]
    E -- "Non-Windows + size > 0" --> G["port_type = string_port\nport_data = content buffer"]
    E -- "Non-Windows + size == 0\n(pseudo-files)" --> F
    F --> J["is_string_port? → false\nShebang check SKIPPED"]
    G --> H["is_string_port? → true\nCheck data[0]=='#' && data[1]=='!'"]
    H -- No shebang --> K[port_position stays at 0]
    H -- Shebang found --> I{newline found?}
    I -- Yes --> L["port_position = pos + 1\n(skip shebang line)"]
    I -- No --> M["port_position = port_data_size\n(empty remainder)"]
    J --> N[push_input_port & parse]
    K --> N
    L --> N
    M --> N
Loading

Reviews (1): Last reviewed commit: "[200_60] Goldfish Scheme 支持 shebang" | Re-trigger Greptile

src/s7.c Outdated
Comment on lines +28939 to +28952
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);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Shebang support silently skipped on Windows

The shebang-skip logic is guarded by is_string_port(port), but on Windows, read_file always creates a file_port (not a string_port) — see the #else branch starting at line 27577 in src/s7.c. This means the #! line is never skipped on Windows, and the interpreter will encounter a syntax error when loading a shebang script on that platform.

The Windows-specific branch sets port_data = NULL and port_data_size = 0, so the is_string_port guard correctly prevents a NULL-dereference crash, but the feature silently fails to work.

If Windows shebang support is needed, a separate code path for file_port (using getc/ungetc or similar) would be required. If Windows is intentionally out of scope, a comment here would clarify the limitation.

src/s7.c Outdated
Comment on lines +28939 to +28952
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);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Shebang skipped for zero-size / pseudo-files (edge case)

When fseek/ftell reports size == 0 (e.g., files under /proc), read_file also creates a file_port, not a string_port. Those files won't receive shebang handling. This is unlikely to matter in practice since /proc pseudo-files don't use shebangs, but it is a subtle inconsistency worth noting alongside the Windows case above.

@da-liii da-liii merged commit a95b3a0 into main Apr 3, 2026
4 checks passed
@da-liii da-liii deleted the da/200_60/shabang branch April 3, 2026 06:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants