[PATCH] Fix ')cd' for SBCL on Windows

9 views
Skip to first unread message

Qian Yun

unread,
Apr 22, 2026, 11:27:41 PM (3 days ago) Apr 22
to fricas-devel
The 'sb-posix' package is available for windows,
although not all functions in that package are available.
But 'chdir' is available.

Also current method (using "truename") to determine
current directory is not reliable for sbcl on windows.
It may return a path string containing "..".

So I change it to use "sb-posix:getcwd", which is available
on both linux and windows.

- Qian
fix-cd-for-sbcl-windows.patch

Qian Yun

unread,
Apr 23, 2026, 1:03:06 AM (3 days ago) Apr 23
to fricas-devel
On 4/23/26 11:27 AM, Qian Yun wrote:
> It may return a path string containing "..".
>

That's because (probe-file "..") will return #P"somepath/../" .

I don't see a need to update the *default-pathname-defaults* value.

- Qian

Waldek Hebisch

unread,
Apr 24, 2026, 7:56:38 AM (yesterday) Apr 24
to fricas...@googlegroups.com
We want that relative name are relative with respect to current
directory. But in sbcl they are/were relative to
*default-pathname-defaults*. When this thing were coded
sb-posix::chdir did not change *default-pathname-defaults*,
so after the call they would get out of sync causing trouble.

--
Waldek Hebisch

Qian Yun

unread,
Apr 24, 2026, 8:32:33 AM (yesterday) Apr 24
to fricas...@googlegroups.com
The only reason I can think of updating *default-pathname-defaults*
is that '(truename "")' depends on it, which is used by
'|get_current_directory|'. But that is changed by this patch as well.

I just tested that removing this *default-pathname-defaults* line
does not break build will sbcl. I also browsed through current sbcl
repo for *default-pathname-defaults* usage, it seems not much is
relying on it.

So is this change good to go? Or do I need to test with an older
sbcl to make sure there's no breakage?

- Qian

Waldek Hebisch

unread,
Apr 24, 2026, 3:34:28 PM (yesterday) Apr 24
to fricas...@googlegroups.com
Merely running build and 'make all-input' is way too little
testing for this case. Main use of 'CHDIR' is implementing
user ')cd' command. There is other use, when making
databases ('merge_info_from_objects') and the third one, to undo
effect of 'CHDIR' in 'merge_info_from_objects'. AFAICS
testsuite when you run it in normal way makes no use of ')cd'.
So you tested _one_ aspect of 'CHDIR'. But after ')cd'
user may do many thing that depend on "current directory".

There was concious effort to limit dependency on Lisp functions
and features. So it is possible that now we do not depend on
*default-pathname-defaults*. It is possible that sbcl changed
so that *default-pathname-defaults* is used less. But to
confirm would need more testing. Concerning old version,
binaries that I create use sbcl 1.4.16, so I would prefer
that this versions works. From time to time I use older
versions, just to check that they work (and they worked
last time that I checked). While supporting them is not
very important, saving one line of code IMO is not worth
breaking compatibility.

--
Waldek Hebisch

Qian Yun

unread,
Apr 24, 2026, 6:40:30 PM (24 hours ago) Apr 24
to fricas...@googlegroups.com
Before this patch, because of the #-:win32,
CHDIR does not change directory, but *d-p-d* is changed.

The posix chdir and getpwd should be a pair, and
they are logically independent of *d-p-d*.

Changelog says current code was made in 2007-06-14,
even before first commit in fricas repo. Pretty sure
pathname handling in sbcl evolves a lot since then.

Also we have "relative-to-absolute", if we want something
relative to current directory, but is in fact relative to
*d-p-d*, then we should use "relative-to-absolute" first.

Can I commit the version removing *d-p-d* after manual
testing with sbcl-1.4.16?

- Qian

Qian Yun

unread,
Apr 24, 2026, 7:43:00 PM (23 hours ago) Apr 24
to fricas...@googlegroups.com
> On 4/25/26 3:34 AM, Waldek Hebisch wrote:
>>
>> Merely running build and 'make all-input' is way too little
>> testing for this case. Main use of 'CHDIR' is implementing
>> user ')cd' command. There is other use, when making
>> databases ('merge_info_from_objects') and the third one, to undo
>> effect of 'CHDIR' in 'merge_info_from_objects'. AFAICS

Looking at 'merge_info_from_objects' feels like opening a can of worms.

1. there is this comment in gdata.boot:

-- FIXME: make this _really_ portable
thisdir := true_name('"./")

Well, this should be changed to |get_current_directory|.

2. the only other call to "true_name" is in "make_databases":

for dir in dir_lst repeat
merge_info_from_objects([], [['dir, true_name(
STRCONC('"./~a", dir))]], true)

2.1 this was translated from lisp, and "STRCONC" is an error,
should be "FORMAT".

2.2 but currently in all calls to "make_databases", "dir_lst"
is nil, so this faulty code never runs.


Is there a legit use of this code? If not, we can remove it.

- Qian

Qian Yun

unread,
Apr 24, 2026, 7:47:00 PM (22 hours ago) Apr 24
to fricas...@googlegroups.com
On 4/25/26 7:42 AM, Qian Yun wrote:
>> On 4/25/26 3:34 AM, Waldek Hebisch wrote:
>>>
>>> Merely running build and 'make all-input' is way too little
>>> testing for this case. Main use of 'CHDIR' is implementing
>>> user ')cd' command. There is other use, when making
>>> databases ('merge_info_from_objects') and the third one, to undo
>>> effect of 'CHDIR' in 'merge_info_from_objects'. AFAICS
>
> Looking at 'merge_info_from_objects' feels like opening a can of worms.
>
> 1. there is this comment in gdata.boot:
>
> -- FIXME: make this _really_ portable
> thisdir := true_name('"./")
>
> Well, this should be changed to |get_current_directory|.
>

I didn't post it, it was supposed to be next commit,
the portable |get_current_directory|:

(defun |get_current_directory| ()
#+:abcl
(|trim_directory_name| (namestring (truename "")))
#+:clisp
(|trim_directory_name| (namestring (ext:default-directory)))
#+:cmu
(nth-value 1 (unix::unix-current-directory))
#+:ecl
(|trim_directory_name| (namestring (ext:getcwd)))
#+:gcl
(si:getcwd)
#+lispworks
(|trim_directory_name| (namestring (system:current-directory)))
#+:openmcl
(ccl::current-directory-name)
#+:poplog
(let ((name (namestring (truename "."))))
(|trim_directory_name| (subseq name 0 (1- (length name)))))
#+:sbcl
(sb-unix:posix-getcwd)
)

- Qian

Waldek Hebisch

unread,
Apr 24, 2026, 7:53:45 PM (22 hours ago) Apr 24
to fricas...@googlegroups.com
On Sat, Apr 25, 2026 at 06:40:26AM +0800, Qian Yun wrote:
> Before this patch, because of the #-:win32,
> CHDIR does not change directory, but *d-p-d* is changed.
>
> The posix chdir and getpwd should be a pair, and
> they are logically independent of *d-p-d*.
>
> Changelog says current code was made in 2007-06-14,
> even before first commit in fricas repo. Pretty sure
> pathname handling in sbcl evolves a lot since then.
>
> Also we have "relative-to-absolute", if we want something
> relative to current directory, but is in fact relative to
> *d-p-d*, then we should use "relative-to-absolute" first.
>
> Can I commit the version removing *d-p-d* after manual
> testing with sbcl-1.4.16?

But _why_ do you want this change?

Currently, when using gcl *default-pathname-defaults* is "",
so it corresponds to current directory without any need for
adjustment. When using ecl I get:

> *default-pathname-defaults*

#P"/sklad/fricas/axp1/pp5/"
> (si:chdir "../pp11")

#P"/sklad/fricas/axp1/pp5/"
> *default-pathname-defaults*

#P"/sklad/fricas/axp1/pp11/"

So as you can see ecl uses full pathname, but it adjust the
pahtname to follow current directory. IIRC both clisp and
openmcl worked the same way. sbcl (and cmucl) are different,
*default-pathname-defaults* is a full pathname but
sb-posix::chdir does not adjust it. When I checked that, in
sbcl there were no Lisp level "change directory" function and
instead user was supposed to adjust *default-pathname-defaults*
and/or use sb-posix::chdir. The code made sure that sbcl
behaviour matched all other Lisp that we use.

Change that you propose would introduce difference between
sbcl and other Lisp-s. Even if there are no bad effects
for me it looks like rather bad idea.

--
Waldek Hebisch

Qian Yun

unread,
Apr 24, 2026, 8:01:47 PM (22 hours ago) Apr 24
to fricas...@googlegroups.com
On 4/25/26 7:53 AM, Waldek Hebisch wrote:
>
> But _why_ do you want this change?
>

1. Logically there's no need.

2. Currently, on sbcl on windows, we may set *d-p-d* to
something like "somepath/..", which is not canonical,
because we are using probe-file not truename.

>
> Change that you propose would introduce difference between
> sbcl and other Lisp-s. Even if there are no bad effects
> for me it looks like rather bad idea.
>

Because of the second point I mentioned above, I'm inclined
to leave *d-p-d* alone rather than try to fix it.

- Qian

Waldek Hebisch

unread,
Apr 24, 2026, 8:21:54 PM (22 hours ago) Apr 24
to fricas...@googlegroups.com
On Sat, Apr 25, 2026 at 08:01:27AM +0800, Qian Yun wrote:
> On 4/25/26 7:53 AM, Waldek Hebisch wrote:
> >
> > But _why_ do you want this change?
> >
>
> 1. Logically there's no need.
>
> 2. Currently, on sbcl on windows, we may set *d-p-d* to
> something like "somepath/..", which is not canonical,
> because we are using probe-file not truename.

Hmm, from Lisp HyperSpec:

: probe-file returns false if there is no file named pathspec, and
: otherwise returns the truename of pathspec.

So it looks like sbcl bug.

--
Waldek Hebisch

Qian Yun

unread,
Apr 24, 2026, 8:42:23 PM (22 hours ago) Apr 24
to fricas...@googlegroups.com
You said you would like to move away from Lisp specific pathname
handling, and use string as representation for pathname.

We just removed "merge-pathname", which depends on *d-p-d*.

In my previous mail in this thread, we can remove some "turename"
calls as well, which on some lisps it depends on *d-p-d*.

I would like to remove *d-p-d* for sbcl in |get_current_directory|.

In asdf-uiop, for sbcl, changing directory does not touch *d-p-d*.
That doesn't breaks thousands of quicklisp packages.

Even if it breaks something in fricas, we will fix it, then
we are one step further away from lisp specific pathname logic.

The alternative approach for this bug is to set *d-p-d* to
(sb-unix:posix-getcwd).

I prefer to remove *d-p-d*. What do you think?

- Qian

Waldek Hebisch

unread,
Apr 24, 2026, 8:48:43 PM (21 hours ago) Apr 24
to fricas...@googlegroups.com
On Sat, Apr 25, 2026 at 07:42:56AM +0800, Qian Yun wrote:
> > On 4/25/26 3:34 AM, Waldek Hebisch wrote:
> >>
> >> Merely running build and 'make all-input' is way too little
> >> testing for this case. Main use of 'CHDIR' is implementing
> >> user ')cd' command. There is other use, when making
> >> databases ('merge_info_from_objects') and the third one, to undo
> >> effect of 'CHDIR' in 'merge_info_from_objects'. AFAICS
>
> Looking at 'merge_info_from_objects' feels like opening a can of worms.

Yes, there is a can of worms. There is a lot of code to support
Aldor files, but we do not use them during normal build. Current
Aldor tests just check a simplest use, but somebody using Aldor
may wish to use much more.

> 1. there is this comment in gdata.boot:
>
> -- FIXME: make this _really_ portable
> thisdir := true_name('"./")
>
> Well, this should be changed to |get_current_directory|.

Yes.

> 2. the only other call to "true_name" is in "make_databases":
>
> for dir in dir_lst repeat
> merge_info_from_objects([], [['dir, true_name(
> STRCONC('"./~a", dir))]], true)
>
> 2.1 this was translated from lisp, and "STRCONC" is an error,
> should be "FORMAT".

Well, '~a' should be gone, that is we shold have STRCONC('"./", dir).
'true_name' probably is not needed at all, but since this was not
tested I just kept it.

> 2.2 but currently in all calls to "make_databases", "dir_lst"
> is nil, so this faulty code never runs.

I did not notice that it was faulty, but I know that we do not use
it. Still, ability to split files into multiple directories looks
useful, so I kept it.

> Is there a legit use of this code? If not, we can remove it.

If you want to split Spad .NRLIB-s into multiple directories, then
you need it because databases must contain info from all .NRLIB-s
and 'merge_info_from_objects' only handles .NRLIB-s in one
directory.

People now seem to write little their own Spad and when they do
they just use ')lib' on each use. But in principle user could
compile own collection of .NRLIB-s in a private directory and
then use 'make_databases' to create version of FriCAS extended
by extra files (so that no ')lib' is needed to use extra functions).

Thinking abut this use case, STRCONC looks undesirable because it
forces use of relative names, while private directories in
principle could exist outside build tree, so absolute name could
be more appropriate.

--
Waldek Hebisch

Waldek Hebisch

unread,
Apr 24, 2026, 9:42:39 PM (21 hours ago) Apr 24
to fricas...@googlegroups.com
On Sat, Apr 25, 2026 at 08:42:18AM +0800, Qian Yun wrote:
> On 4/25/26 8:21 AM, Waldek Hebisch wrote:
> > On Sat, Apr 25, 2026 at 08:01:27AM +0800, Qian Yun wrote:
> >> On 4/25/26 7:53 AM, Waldek Hebisch wrote:
> >>>
> >>> But _why_ do you want this change?
> >>>
> >>
> >> 1. Logically there's no need.
> >>
> >> 2. Currently, on sbcl on windows, we may set *d-p-d* to
> >> something like "somepath/..", which is not canonical,
> >> because we are using probe-file not truename.
> >
> > Hmm, from Lisp HyperSpec:
> >
> > : probe-file returns false if there is no file named pathspec, and
> > : otherwise returns the truename of pathspec.
> >
> > So it looks like sbcl bug.
> >
>
> You said you would like to move away from Lisp specific pathname
> handling, and use string as representation for pathname.
>
> We just removed "merge-pathname", which depends on *d-p-d*.

Let me explain it a bit more. We need to use Lisp calls,
like OPEN, LOAD, COMPILE-FILE, WITH-OPEN-FILE. Maybe this is
full list, maybe not. I would like them to behave as normal
OS functions: given a string representing relative name, they
should handle corresponding file relative to current directory.

Look at COMPILE-FILE for example (this one is nasty). From
HyperSpec:

: input-file---a pathname designator. (Default fillers for
: unspecified components are taken from *default-pathname-defaults*.)

So, to get desired behaviour for relative names *default-pathname-defaults*
must point to current directory, and AFAICS this is enough.

IIRC output file is worse. In HyperSpec I just see "implementation
defined", but IIRC older spec said that full output pathname is
result of 'merge-pathname' applied to input and output arguments of
COMPILE-FILE. In simple cases it worked naturally, but for more
complicated names the result was unexpected (except maybe for people
who know Lisp spec very well). 'relative-to-absolute' was
created to solve this problem: by converting to absolute name
we defeated 'merge-pathname' done by Lisp implementation.

In principle we could try to use 'relative-to-absolute' to
defeat 'merge-pathname' in other places, but to me it looks
simpler and more efficient just make sure that
*default-pathname-defaults* always points to current directory.

> In my previous mail in this thread, we can remove some "turename"
> calls as well, which on some lisps it depends on *d-p-d*.
>
> I would like to remove *d-p-d* for sbcl in |get_current_directory|.

Sure. In a sense most calls to 'truename' are suspect, that is
just using given string as a name should work. Valid uses are
when we need absolute name and possibly if we want to check if
the name is on some list of names. But old code did twisty
things and used 'truename' quite a lot.

> In asdf-uiop, for sbcl, changing directory does not touch *d-p-d*.
> That doesn't breaks thousands of quicklisp packages.
>
> Even if it breaks something in fricas, we will fix it, then
> we are one step further away from lisp specific pathname logic.

As I wrote, we set *default-pathname-defaults* to neutralize
Lisp specific pathname handling.

> The alternative approach for this bug is to set *d-p-d* to
> (sb-unix:posix-getcwd).
>
> I prefer to remove *d-p-d*. What do you think?

You may want to test, but AFAIR without any corrective action
after changing current directory is sbcl, calling Lisp functions
taking filenames as arguments did not work correctly for relative
names. Setting *default-pathname-defaults* fixed this. Since
this behaviour was mandated by HyperSpec, it is unlikely to
change between sbcl versions.

--
Waldek Hebisch

Ralf Hemmecke

unread,
1:02 AM (17 hours ago) 1:02 AM
to fricas...@googlegroups.com
On 4/25/26 02:48, Waldek Hebisch wrote:
> People now seem to write little their own Spad and when they do
> they just use ')lib' on each use. But in principle user could
> compile own collection of .NRLIB-s in a private directory and
> then use 'make_databases' to create version of FriCAS extended
> by extra files (so that no ')lib' is needed to use extra functions).

Oh!

That sounds interesting. I am not in real need of this, since loading
via )lib is not a big deal, but I am not aware that I have read how to
do what you describe above in our official documentation. I don't think
that an ordinary FriCAS user knows about such an extension mechanism.

Ralf
Reply all
Reply to author
Forward
0 new messages