Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions devel/200_60.md
Original file line number Diff line number Diff line change
@@ -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 跳过逻辑
36 changes: 36 additions & 0 deletions src/s7.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading