Skip to content

Commit 6822f9b

Browse files
gh-55: Expand search paths.
1 parent 957631b commit 6822f9b

File tree

22 files changed

+79
-37
lines changed

22 files changed

+79
-37
lines changed

build.ps1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<#
22
build.ps1
33
Compiles the interpreter in a temporary directory and copies the resulting EXE
4-
back into this repo. Also discovers extension C sources under ext/ and lib/
4+
back into this repo. Also discovers extension C sources under stdext/ and stdlib/
55
and compiles each one into a dynamic library next to its source file.
66
77
Requires: run from a Developer Command Prompt for Visual Studio where cl.exe is on PATH.
@@ -12,8 +12,8 @@ Usage (from Prefix-C folder):
1212
$script = Split-Path -Parent $MyInvocation.MyCommand.Definition
1313
$src = Join-Path $script "src"
1414
$extRoots = @(
15-
(Join-Path $script "ext"),
16-
(Join-Path $script "lib"),
15+
(Join-Path $script "stdext"),
16+
(Join-Path $script "stdlib"),
1717
(Join-Path $script "tests")
1818
)
1919

@@ -76,7 +76,7 @@ try {
7676
}
7777

7878
if ($extSources.Count -eq 0) {
79-
Write-Host "No extension C sources found under ext/ or lib/."
79+
Write-Host "No extension C sources found under stdext/ or stdlib/."
8080
} else {
8181
Write-Host "Found $($extSources.Count) extension source file(s)."
8282
}

docs/SPECIFICATION.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,9 @@
330330
331331
## 8. Standard Library
332332
333-
The standard library is a group of modules for common use cases distributed with the interpreter. at the Prefix directory \lib (or /lib on non-Windows systems).
333+
The standard library is a group of modules for common use cases distributed with the interpreter. These bundled modules live under `stdlib/`. Module/package search paths for `IMPORT` and `IMPORT_PATH` MUST include `stdlib/` immediately before `lib/` so that standard, bundled modules take precedence over legacy or user-installed modules in `lib/`.
334+
335+
Extension libraries shipped with the interpreter live under `stdext/`. Extension search paths MUST include `stdext/` immediately before `ext/` so that bundled extensions are preferred over user-installed `ext/` copies.
334336
335337
## 9. Tracebacks and Error Reporting
336338

ext/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

lib/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

src/builtins.c

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6043,56 +6043,79 @@ static Value builtin_import(Interpreter* interp, Value* args, int argc, Expr** a
60436043
char* found_path = NULL;
60446044
char* srcbuf = NULL;
60456045

6046-
// Search locations: referring dir, then primary-source lib/, then executable lib/.
6047-
const char* search_dirs[3];
6046+
/* Search locations: referring dir, then primary-source stdlib/, primary-source lib/,
6047+
then executable stdlib/, executable lib/. This ensures `stdlib/` is tried
6048+
immediately before `lib/` as required by gh-55. */
6049+
const char* search_dirs[5];
60486050
search_dirs[0] = referer_dir;
60496051

60506052
EnvEntry* primary_src_entry = interp && interp->global_env ? env_get_entry(interp->global_env, "__MODULE_SOURCE__") : NULL;
6051-
char primary_lib_dir[1024];
6052-
primary_lib_dir[0] = '\0';
6053+
char primary_base_dir[1024];
6054+
primary_base_dir[0] = '\0';
60536055
if (primary_src_entry && primary_src_entry->initialized && primary_src_entry->value.type == VAL_STR && primary_src_entry->value.as.s && primary_src_entry->value.as.s[0] != '\0') {
6054-
strncpy(primary_lib_dir, primary_src_entry->value.as.s, sizeof(primary_lib_dir)-1);
6055-
primary_lib_dir[sizeof(primary_lib_dir)-1] = '\0';
6056+
strncpy(primary_base_dir, primary_src_entry->value.as.s, sizeof(primary_base_dir)-1);
6057+
primary_base_dir[sizeof(primary_base_dir)-1] = '\0';
60566058
char* last_sep = NULL;
6057-
for (char* q = primary_lib_dir; *q; q++) if (*q == '/' || *q == '\\') last_sep = q;
6059+
for (char* q = primary_base_dir; *q; q++) if (*q == '/' || *q == '\\') last_sep = q;
60586060
if (last_sep) *last_sep = '\0';
6059-
size_t used = strnlen(primary_lib_dir, sizeof(primary_lib_dir));
6060-
if (used + 4 < sizeof(primary_lib_dir)) {
6061-
primary_lib_dir[used] = '/';
6062-
primary_lib_dir[used+1] = 'l';
6063-
primary_lib_dir[used+2] = 'i';
6064-
primary_lib_dir[used+3] = 'b';
6065-
primary_lib_dir[used+4] = '\0';
6066-
}
6067-
search_dirs[1] = primary_lib_dir;
6061+
size_t used = strnlen(primary_base_dir, sizeof(primary_base_dir));
6062+
/* primary stdlib */
6063+
if (used + 7 < sizeof(primary_base_dir)) {
6064+
primary_base_dir[used] = '/';
6065+
memcpy(primary_base_dir + used + 1, "stdlib", 6);
6066+
primary_base_dir[used+7] = '\0';
6067+
search_dirs[1] = primary_base_dir;
6068+
} else {
6069+
search_dirs[1] = "stdlib";
6070+
}
6071+
/* construct a separate primary lib string for lib/ */
6072+
static char primary_lib_dir[1024];
6073+
primary_lib_dir[0] = '\0';
6074+
strncpy(primary_lib_dir, primary_base_dir, sizeof(primary_lib_dir)-1);
6075+
primary_lib_dir[sizeof(primary_lib_dir)-1] = '\0';
6076+
/* replace trailing "stdlib" with "lib" */
6077+
char* tail = strrchr(primary_lib_dir, '/');
6078+
if (tail) {
6079+
strcpy(tail+1, "lib");
6080+
}
6081+
search_dirs[2] = primary_lib_dir;
60686082
} else {
6069-
search_dirs[1] = "lib";
6083+
search_dirs[1] = "stdlib";
6084+
search_dirs[2] = "lib";
60706085
}
60716086

6072-
char exe_lib_dir[1024];
6087+
char exe_base_dir[1024];
6088+
exe_base_dir[0] = '\0';
6089+
static char exe_lib_dir[1024];
60736090
exe_lib_dir[0] = '\0';
60746091
if (g_argv && g_argv[0] && g_argv[0][0] != '\0') {
6075-
strncpy(exe_lib_dir, g_argv[0], sizeof(exe_lib_dir)-1);
6076-
exe_lib_dir[sizeof(exe_lib_dir)-1] = '\0';
6092+
strncpy(exe_base_dir, g_argv[0], sizeof(exe_base_dir)-1);
6093+
exe_base_dir[sizeof(exe_base_dir)-1] = '\0';
60776094
char* last_sep = NULL;
6078-
for (char* q = exe_lib_dir; *q; q++) if (*q == '/' || *q == '\\') last_sep = q;
6095+
for (char* q = exe_base_dir; *q; q++) if (*q == '/' || *q == '\\') last_sep = q;
60796096
if (last_sep) *last_sep = '\0';
6080-
size_t used = strnlen(exe_lib_dir, sizeof(exe_lib_dir));
6081-
if (used + 4 < sizeof(exe_lib_dir)) {
6082-
exe_lib_dir[used] = '/';
6083-
exe_lib_dir[used+1] = 'l';
6084-
exe_lib_dir[used+2] = 'i';
6085-
exe_lib_dir[used+3] = 'b';
6086-
exe_lib_dir[used+4] = '\0';
6087-
search_dirs[2] = exe_lib_dir;
6097+
size_t used = strnlen(exe_base_dir, sizeof(exe_base_dir));
6098+
if (used + 7 < sizeof(exe_base_dir)) {
6099+
exe_base_dir[used] = '/';
6100+
memcpy(exe_base_dir + used + 1, "stdlib", 6);
6101+
exe_base_dir[used+7] = '\0';
6102+
search_dirs[3] = exe_base_dir;
6103+
/* construct exe lib by replacing trailing part */
6104+
strncpy(exe_lib_dir, exe_base_dir, sizeof(exe_lib_dir)-1);
6105+
exe_lib_dir[sizeof(exe_lib_dir)-1] = '\0';
6106+
char* tail = strrchr(exe_lib_dir, '/');
6107+
if (tail) strcpy(tail+1, "lib");
6108+
search_dirs[4] = exe_lib_dir;
60886109
} else {
6089-
search_dirs[2] = NULL;
6110+
search_dirs[3] = "stdlib";
6111+
search_dirs[4] = "lib";
60906112
}
60916113
} else {
6092-
search_dirs[2] = NULL;
6114+
search_dirs[3] = "stdlib";
6115+
search_dirs[4] = "lib";
60936116
}
60946117

6095-
for (int sd = 0; sd < 3 && !found_path; sd++) {
6118+
for (int sd = 0; sd < 5 && !found_path; sd++) {
60966119
const char* sdir = search_dirs[sd];
60976120
if (!sdir) continue;
60986121

src/extensions.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,19 @@ static char* resolve_extension_path(const char* input, const char* base_dir) {
167167
}
168168

169169
if (g_interpreter_dir && g_interpreter_dir[0] != '\0') {
170+
/* Prefer stdext/ before ext/ as per gh-55 */
171+
char* stdext_dir = path_join2(g_interpreter_dir, "stdext");
172+
if (stdext_dir) {
173+
char* p_std = path_join2(stdext_dir, input);
174+
free(stdext_dir);
175+
if (p_std && file_exists_regular(p_std)) {
176+
char* c = canonicalize_existing_path(p_std);
177+
free(p_std);
178+
return c;
179+
}
180+
free(p_std);
181+
}
182+
170183
char* ext_dir = path_join2(g_interpreter_dir, "ext");
171184
char* p = path_join2(ext_dir, input);
172185
free(ext_dir);
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)