From: Richard M Kreuter
Subject: Logical pathname namestring syntax
Date: 
Message-ID: <87zlvq37b7.fsf@progn.net>
Suppose we do this:

(setf (logical-pathname-translations "MY-HOST") ())
=> NIL
(setf *default-pathname-defaults* (pathname "MY-HOST:"))
=> ;; implementation-dependent

What should the following return?

(pathname-directory "foo.lisp.newest")
=> ???

A few implementations return NIL, a few (:ABSOLUTE).  This proves
significant for merging, of course.

--
RmK

From: Dan Muller
Subject: Re: Logical pathname namestring syntax
Date: 
Message-ID: <G9jej.2373$pr6.473@nlpi070.nbdc.sbc.com>
Richard M Kreuter <·······@progn.net> writes:
> Suppose we do this:
>
> (setf (logical-pathname-translations "MY-HOST") ())
> => NIL
> (setf *default-pathname-defaults* (pathname "MY-HOST:"))
> => ;; implementation-dependent
>
> What should the following return?
>
> (pathname-directory "foo.lisp.newest")
> => ???
>
> A few implementations return NIL, a few (:ABSOLUTE).  This proves
> significant for merging, of course.

I've just been looking at pathnames again in detail. I'm interested in
these kinds of questions because I'm trying to do work on some
portable Lisp software that does a lot of work with files. I'll take a
crack at your question so that I get the opportunity to be
corrected. :)

It isn't made real explicit in the standard, but I think it is implied
that a namestring used as a pathname designator is coerced to a
pathname as if by PATHNAME. PATHNAME is given huge leeway in
interpreting a namestring that isn't a logical pathname
namestring. Some people make a reasonable-seeming assumption that
(PATHNAME namestring) should be equivalent to (VALUES
(PARSE-NAMESTRING namestring)), but the standard doesn't say so. [1,2]

So your call to PATHNAME-DIRECTORY evokes implementation-dependent
behavior.

Particularly, in 19.1.1, "Namestrings as Filenames", the standard
says:

    A conforming program must never unconditionally use a literal
    namestring other than a logical pathname namestring because Common
    Lisp does not define any namestring syntax other than that for
    logical pathnames that would be guaranteed to be
    portable. However, a conforming program can, if it is careful,
    successfully manipulate user-supplied data which contains or
    refers to non-portable namestrings.

    A namestring can be coerced to a pathname by the functions
    pathname or parse-namestring.

Also, the examples given in the standard with PATHNAME are instructive
in that they're deliberately ambiguous. :)

The standard says of *DEFAULT-PATHNAME-DEFAULT* that it is "used as
the default whenever a function needs a default pathname and one is
not supplied". I guess one could interpret PATHNAME as needing the
host part of a default pathname in order to do its job, but it's
specification is so vague that this is questionable. Let's assume that
this is true. If you also accept the notion that the string argument
to PATHNAME-DIRECTORY is coerced as if by PATHNAME, then your example
would be equivalent to:

    (pathname-directory "MY-HOST:foo.lisp.newest")

The argument should then be coerced to #P"MY-HOST:FOO.LISP.NEWEST", so
the result should be NIL.

Another interesting question is what PATHNAME-HOST would return. I
have no answer for that.

[1] http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/82726fe0ec1c233f/f7b93de5a35a2c8a
[2] http://www.lisp.org/HyperSpec/Body/fun_pathname.html
From: Richard M Kreuter
Subject: Re: Logical pathname namestring syntax
Date: 
Message-ID: <87ve6d3bmr.fsf@progn.net>
Dan Muller <·········@sneakemail.com> writes:

> Richard M Kreuter <·······@progn.net> writes:
>> Suppose we do this:
>>
>> (setf (logical-pathname-translations "MY-HOST") ())
>> => NIL
>> (setf *default-pathname-defaults* (pathname "MY-HOST:"))
>> => ;; implementation-dependent
>>
>> What should the following return?
>>
>> (pathname-directory "foo.lisp.newest")
>> => ???
>>
>> A few implementations return NIL, a few (:ABSOLUTE).  This proves
>> significant for merging, of course.
>
> It isn't made real explicit in the standard, but I think it is implied
> that a namestring used as a pathname designator is coerced to a
> pathname as if by PATHNAME...

Oh.  I took it for granted that a namestring is coerced as if by
PATHNAME and that PATHNAME parses namestrings as if by
PARSE-NAMESTRING, but you're right that even that's not specified.  I
guess that should be unsurprising.

> If you also accept the notion that the string argument to
> PATHNAME-DIRECTORY is coerced as if by PATHNAME, then your example
> would be equivalent to:
>
>     (pathname-directory "MY-HOST:foo.lisp.newest")
>
> The argument should then be coerced to #P"MY-HOST:FOO.LISP.NEWEST", so
> the result should be NIL.

This is the detail I'm wondering about, and about which
implementations differ: some parse a logical pathname namestring that
lacks a directory into a pathname whose directory is (:ABSOLUTE),
others into a pathname whose directory is NIL.

--
RmK
From: Vassil Nikolov
Subject: Re: Logical pathname namestring syntax
Date: 
Message-ID: <snw8x355z3j.fsf@luna.vassil.nikolov.names>
Richard M Kreuter <·······@progn.net> writes:

> Dan Muller <·········@sneakemail.com> writes:
>
>> Richard M Kreuter <·······@progn.net> writes:
>>> Suppose we do this:
>>>
>>> (setf (logical-pathname-translations "MY-HOST") ())
>>> => NIL
>>> (setf *default-pathname-defaults* (pathname "MY-HOST:"))
>>> => ;; implementation-dependent
>>>
>>> What should the following return?
>>>
>>> (pathname-directory "foo.lisp.newest")
>>> => ???
>>>
>>> A few implementations return NIL, a few (:ABSOLUTE).  This proves
>>> significant for merging, of course.
>> ...
>> If you also accept the notion that the string argument to
>> PATHNAME-DIRECTORY is coerced as if by PATHNAME, then your example
>> would be equivalent to:
>>
>>     (pathname-directory "MY-HOST:foo.lisp.newest")
>>
>> The argument should then be coerced to #P"MY-HOST:FOO.LISP.NEWEST", so
>> the result should be NIL.
>
> This is the detail I'm wondering about, and about which
> implementations differ: some parse a logical pathname namestring that
> lacks a directory into a pathname whose directory is (:ABSOLUTE),
> others into a pathname whose directory is NIL.

  I think this boils down to the value of

    (progn
      (setf (logical-pathname-translations "lh") '())
      (typep (pathname "lh:foo.lisp.newest") 'logical-pathname))

  and I get T from SBCL as I expected, but NIL from CLisp, which I did
  not expect.  I am not sure that CLisp is right in this case.

  Note that with both SBCL and CLisp,

    (progn
      (setf (logical-pathname-translations "lh") '())
      (pathname-directory (logical-pathname "lh:foo.lisp.newest")))
    => (:absolute)

  so logical pathnames themselves do work properly in this regard in
  both.

  ---Vassil.


-- 
Bound variables, free programmers.
From: Richard M Kreuter
Subject: Re: Logical pathname namestring syntax
Date: 
Message-ID: <87hchtqhlg.fsf@progn.net>
Vassil Nikolov <···············@pobox.com> writes:
> Richard M Kreuter <·······@progn.net> writes:
>
>> This is the detail I'm wondering about, and about which
>> implementations differ: some parse a logical pathname namestring
>> that lacks a directory into a pathname whose directory is
>> (:ABSOLUTE), others into a pathname whose directory is NIL.
>
>   I think this boils down to the value of
>
>     (progn
>       (setf (logical-pathname-translations "lh") '())
>       (typep (pathname "lh:foo.lisp.newest") 'logical-pathname))
>
>   and I get T from SBCL as I expected, but NIL from CLisp, which I did
>   not expect.  I am not sure that CLisp is right in this case.

I forgot that Clisp defaults to not conforming about how it parses
namestrings:

http://clisp.podval.org/impnotes/filename-dict.html#parsename

>   Note that with both SBCL and CLisp,
>
>     (progn
>       (setf (logical-pathname-translations "lh") '())
>       (pathname-directory (logical-pathname "lh:foo.lisp.newest")))
>     => (:absolute)
>
>   so logical pathnames themselves do work properly in this regard in
>   both.

Again, this is my question: is that a good parse?  ISTM that parsing
the absence of directories to NIL makes logical pathnames somewhat
more convenient, since that parse lets you use namestrings containing
just a name, type, and version, and use *DEFAULT-PATHNAME-DEFAULTS* as
a "current working logical directory", so to speak.

(Note that if you want logical pathname namestrings not to be lossy,
the two pathnames

  (make-pathname :host "FOO" :directory '(:absolute))
  (make-pathname :host "FOO" :directory '())

cannot both have namestrings.  And ISTM to be desirable for
namestringification to be non-lossy, though it's very lossy on most
implementations.  But that's a separate point.)

--
RmK
From: Vassil Nikolov
Subject: Re: Logical pathname namestring syntax
Date: 
Message-ID: <snwfxxd3xm6.fsf@luna.vassil.nikolov.names>
Richard M Kreuter <·······@progn.net> writes:
> I forgot that Clisp defaults to not conforming about how it parses
> namestrings:
>
> http://clisp.podval.org/impnotes/filename-dict.html#parsename

  Ah, that explains it then.  Thanks for pointing it out.

>> ...
>>       (pathname-directory (logical-pathname "lh:foo.lisp.newest"))
>>     => (:absolute)
>> ...
> Again, this is my question: is that a good parse?  ISTM that parsing
> the absence of directories to NIL makes logical pathnames somewhat
> more convenient, since that parse lets you use namestrings containing
> just a name, type, and version, and use *DEFAULT-PATHNAME-DEFAULTS* as
> a "current working logical directory", so to speak.

  But note that a logical pathname is relative if it _has_ a leading
  semicolon in the directory part:

    (progn
      (setf (logical-pathname-translations "lh") '())
      (pathname-directory (logical-pathname "lh:;foo.lisp.newest")))
    => (:relative)

  and then

    (merge-pathnames (logical-pathname "lh:;foo.lisp.newest")
                     (logical-pathname "lh:bar;baz.lisp.newest"))
    => #P"LH:BAR;FOO.LISP.NEWEST"  ;whose directory is (:absolute "BAR")

  so I think you do have a way to get what you want.

  ---Vassil.


-- 
Bound variables, free programmers.
From: Richard M Kreuter
Subject: Re: Logical pathname namestring syntax
Date: 
Message-ID: <87d4sgql0a.fsf@progn.net>
Vassil Nikolov <···············@pobox.com> writes:
> Richard M Kreuter <·······@progn.net> writes:

>>>       (pathname-directory (logical-pathname "lh:foo.lisp.newest"))
>>>     => (:absolute)
>>> ...

>> Again, this is my question: is that a good parse?  ISTM that
>> parsing the absence of directories to NIL makes logical pathnames
>> somewhat more convenient, since that parse lets you use namestrings
>> containing just a name, type, and version, and use
>> *DEFAULT-PATHNAME-DEFAULTS* as a "current working logical
>> directory", so to speak.
>
>   But note that a logical pathname is relative if it _has_ a leading
>   semicolon in the directory part:
>
>     (progn
>       (setf (logical-pathname-translations "lh") '())
>       (pathname-directory (logical-pathname "lh:;foo.lisp.newest")))
>     => (:relative)

(This is offtopic, but in 19.2.2.4.2, we have

  The list ‘(:relative)’ has the same meaning as ‘nil’ and hence is
  not used.

so maybe implementations are supposed to canonicalize (:RELATIVE) to
NIL during parsing and construction.  I'm not certain, though: NIL
does not have the same meaning as non-NIL values for all pathname
operations (e.g., PATHNAME-MATCH-P fills in "missing" components).)

>   and then
>
>     (merge-pathnames (logical-pathname "lh:;foo.lisp.newest")
>                      (logical-pathname "lh:bar;baz.lisp.newest"))
>     => #P"LH:BAR;FOO.LISP.NEWEST"  ;whose directory is (:absolute "BAR")
>
>   so I think you do have a way to get what you want.

I think we're going in circles.  If it's a valid interpretation of
19.3.1 that the absence of directories in a logical pathname
namestring parses as NIL, then it would be consistent to also say that
a semicolon before an absence of directories in a namestring doesn't
parse.  So I'm not convinced that "LH:;FOO.LISP.NEWEST" is required to
parse, at least not if both interpretations are valid.

--
RmK
From: Vassil Nikolov
Subject: Re: Logical pathname namestring syntax
Date: 
Message-ID: <snwd4sg2ni5.fsf@luna.vassil.nikolov.name>
Richard M Kreuter <·······@progn.net> writes:

> Vassil Nikolov <···············@pobox.com> writes:
>> ...
>>     (progn
>>       (setf (logical-pathname-translations "lh") '())
>>       (pathname-directory (logical-pathname "lh:;foo.lisp.newest")))
>>     => (:relative)
>
> This is offtopic, but in [19.2.2.4.3], we have
>
>   The list (:RELATIVE) has the same meaning as NIL and hence is
>   not used.
>
> so maybe implementations are supposed to canonicalize (:RELATIVE) to
> NIL during parsing and construction.

  That sounds like undue burden for implementors.  Perhaps this was a
  (very minor) point that was missed during text cleanup (thinking
  that "and hence is not used" might perhaps be better off removed).
  Perhaps not.  In any case, this looks like a non-issue to me, or
  very nearly so.

> ...
>>     (merge-pathnames (logical-pathname "lh:;foo.lisp.newest")
>>                      (logical-pathname "lh:bar;baz.lisp.newest"))
>>     => #P"LH:BAR;FOO.LISP.NEWEST"  ;whose directory is (:absolute "BAR")
>>
>>   so I think you do have a way to get what you want.
>
> I think we're going in circles.  If it's a valid interpretation of
> 19.3.1 that the absence of directories in a logical pathname
> namestring parses as NIL, then it would be consistent to also say that
> a semicolon before an absence of directories in a namestring doesn't
> parse.  So I'm not convinced that "LH:;FOO.LISP.NEWEST" is required to
> parse, at least not if both interpretations are valid.

  But see the syntax for <logical-pathname> in 19.3.1 and the
  <relative-directory-marker> part in particular, and then the first
  paragraph of 19.3.1.1.3 ("If a <relative-directory-marker> precedes
  the <directories>, the directory component parsed is as _relative_;
  otherwise, the directory component is parsed as _absolute_.").

  ---Vassil.


-- 
Bound variables, free programmers.