From: Pascal Bourguignon
Subject: Need Help from a Pathname Guru
Date: 
Message-ID: <87r862u7sa.fsf@thalassa.informatimago.com>
I've got a pathname to  a directory, most probably a string containing
an implementation specific pathname entered by the user.

(In  fact, I'll  start with  a string  containing the  unix path  to a
directory, but it could as well be a logical pathname).


I want  to "append" **/* to  it, that is, to  append :wild-inferior to
the pathname directory, and put :wild into the pathname name, type and
version.


I thought  of using MAKE-PATHNAME, to  buil the new  pathname, but how
can I get the pathname directory under a list of string representation
for  sure?   (PATHNAME-DIRECTORY  even  allows the  implementation  to
return anything it wants).


-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.

From: Kent M Pitman
Subject: Re: Need Help from a Pathname Guru
Date: 
Message-ID: <sfw65neoj82.fsf@shell01.TheWorld.com>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> I've got a pathname to  a directory, most probably a string containing
> an implementation specific pathname entered by the user.
> 
> (In  fact, I'll  start with  a string  containing the  unix path  to a
> directory, but it could as well be a logical pathname).
> 
> 
> I want  to "append" **/* to  it, that is, to  append :wild-inferior to

:wild-inferiors

> the pathname directory, and put :wild into the pathname name, type and
> version.
> 
> I thought  of using MAKE-PATHNAME, to  buil the new  pathname, but how
> can I get the pathname directory under a list of string representation
> for  sure?   (PATHNAME-DIRECTORY  even  allows the  implementation  to
> return anything it wants).

I'm not sure I understand this last concern.  PATHNAME-DIRECTORY has to
return the directory.  What do you mean?

This problem is not trivial, but I think you're overstating the complexity.
Your task breaks down as follows...

If the user has entered a pathname, he might have entered:

  1. /foo/bar            <-- the name of the dir as a filename
  2. /foo/bar/           <-- the name of the dir as a directory, with no name
  3. /foo/bar/something  <-- something in the dir

Most implementations offer a "directory-p" predicate.  Find that.  It will
help you screen out the last case.  It may help you recognize the first case,
too.

The second case is already in the form you need, but if you have the first
case, you might need an operator such as the following.  (Prefer the natively
supplied one if your implementation offers one.)

 (defun pathname-as-directory (pathname)
   ;; No, I didn't test this. -kmp
   (let ((pathname-host (pathname-host pathname :case :common))
         (pathname-name (pathname-name pathname :case :common))
         (pathname-type (pathname-type pathname :case :common)))
     (check-type pathname-name (or string (eql :wild)))
     (check-type pathname-type (member nil :unspecific))
     (merge-pathnames (make-pathname :host pathname-host
                                     :directory `(:relative ,pathname-name)
                                     :case :common)
                      (make-pathname :name nil :type nil :version nil
                                     :defaults pathname))))

Once you've got something in the format where all of the directory is really
in the directory, I think you should just be able to do what you said in
your problem description:

 (merge-pathnames (make-pathname :host (pathname-host pathname :case :common)
                                 :directory '(:relative :wild-inferiors)
                                 :name :wild :type :wild :version :wild
                                 :case :common)
                  (pathname-as-directory pathname))
From: Pascal Bourguignon
Subject: Re: Need Help from a Pathname Guru
Date: 
Message-ID: <87llwau42u.fsf@thalassa.informatimago.com>
Kent M Pitman <······@world.std.com> writes:

> Pascal Bourguignon <····@thalassa.informatimago.com> writes:
> 
> > I've got a pathname to  a directory, most probably a string containing
> > an implementation specific pathname entered by the user.
> > 
> > (In  fact, I'll  start with  a string  containing the  unix path  to a
> > directory, but it could as well be a logical pathname).
> > 
> > 
> > I want  to "append" **/* to  it, that is, to  append :wild-inferior to
> 
> :wild-inferiors
> 
> > the pathname directory, and put :wild into the pathname name, type and
> > version.
> > 
> > I thought  of using MAKE-PATHNAME, to  buil the new  pathname, but how
> > can I get the pathname directory under a list of string representation
> > for  sure?   (PATHNAME-DIRECTORY  even  allows the  implementation  to
> > return anything it wants).
> 
> I'm not sure I understand this last concern.  PATHNAME-DIRECTORY has to
> return the directory.  What do you mean?
> 
> This problem is not trivial, but I think you're overstating the complexity.
> Your task breaks down as follows...
> [...]
> Once you've got something in the format where all of the directory is really
> in the directory, I think you should just be able to do what you said in
> your problem description:
> 
>  (merge-pathnames (make-pathname :host (pathname-host pathname :case :common)
>                                  :directory '(:relative :wild-inferiors)
>                                  :name :wild :type :wild :version :wild
>                                  :case :common)
>                   (pathname-as-directory pathname))

That's  where  the difficulty  lies.   I hoped  to  do  that, but  the
specifications of MERGE-PATHNAMES say:

    If (pathname-directory default-pathname) is not a list or
    (pathname-directory pathname) is not a list whose car is :relative,
    the merged directory is (or (pathname-directory pathname)
    (pathname-directory default-pathname))

Since the implementation of  PATHNAME-DIRECTORY may return anything it
deems a  "valid directory component",  (like #<dircomponent-42>), that
may well  not be a  list, then we  won't get the wanted  behavior from
MERGE-PATHNAMES.


The question is: how, given  a pathname (under whatever form), can one
obtain  a  list  of  the  form  (:ABSOLUTE  string...)  or  (:RELATIVE
string...)?

A  subsidiary  question  would  be:  how to  get  a  logical  pathname
namestring from  a pathname? (Since  the syntax of a  logical pathname
namestring is specified  and portable, it would then  be simple enough
to parse it to get the wanted list form).





On the  other hand,  if I restrict  myself to  unix path names,  I can
parse them and  build the directory list myself,  and abandon the lisp
paths... :-(

-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
From: Kent M Pitman
Subject: Re: Need Help from a Pathname Guru
Date: 
Message-ID: <sfwsmqi906v.fsf@shell01.TheWorld.com>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> > Once you've got something in the format where all of the directory
> > is really in the directory, I think you should just be able to do
> > what you said in your problem description:
> > 
> >  (merge-pathnames
> >    (make-pathname
> >      :host (pathname-host pathname :case :common)
> >      :directory '(:relative :wild-inferiors)
> >      :name :wild :type :wild :version :wild
> >      :case :common)
> >    (pathname-as-directory pathname))
> 
> That's  where  the difficulty  lies.   I hoped  to  do  that, but  the
> specifications of MERGE-PATHNAMES say:
> 
>     If (pathname-directory default-pathname) is not a list or
>     (pathname-directory pathname) is not a list whose car is :relative,
>     the merged directory is (or (pathname-directory pathname)
>     (pathname-directory default-pathname))
> 
> Since the implementation of  PATHNAME-DIRECTORY may return anything it
> deems a  "valid directory component",  (like #<dircomponent-42>), that
> may well  not be a  list, then we  won't get the wanted  behavior from
> MERGE-PATHNAMES.

Unless you're citing an implementation that does this, I think you're
just chasing shadows.

The fact is that the pathnames dir is the wost written of any of them.
It was a tangled mess and it was next on my list of chapters to untangle
when we ran out of time/funds and had to wind up the spec.

But first, to my knowledge, all implementations are quite consistent on
the point that directories are 

 NIL
 or
 :WILD [meaning (:ABSOLUTE :WILD)]
 or
 (:ABSOLUTE {component}* ) 
 or
 (:RELATIVE {component}* ) 

But regardless, I don't know of any implementation of MERGE-PATHNAMES
that doesn't correctly merge things according to what I said above.

> The question is: how, given  a pathname (under whatever form), can one
> obtain  a  list  of  the  form  (:ABSOLUTE  string...)  or  (:RELATIVE
> string...)?

You can't.  Because NIL and :WILD are valid fillers.  :WILD can be
canonicalized, but NIL is canonical.  I don't know any implementation
that doesn't canonicalize :WILD as a filler, so I claim you can just
call PATHNAME-DIRECTORY to do that.

If you think this is not so in all implementations, you should cite a
specific implementation and then do a comparison with other implementations.
I don't like talking about "what might be" for stuff like this where
some simple community pressure can typically get things into line.
All the implementors want to do the "right thing".  Most just don't know
what the trouble spots are.

To my knowledge, this is not, in practice, a trouble spot.

> A  subsidiary  question  would  be:  how to  get  a  logical  pathname
> namestring from  a pathname? (Since  the syntax of a  logical pathname
> namestring is specified  and portable, it would then  be simple enough
> to parse it to get the wanted list form).

NAMESTRING if the pathname is a logical pathname.

There is no operator defined for untranslating a physical pathname 
through a set of logical pathnames.  It's not something you're supposed
to ever need to do.  It's not an operation we purported to say was
available. Why do you think you need this?

> On the  other hand,  if I restrict  myself to  unix path names,  I can
> parse them and  build the directory list myself,  and abandon the lisp
> paths... :-(

IMO, this is paranoia and superstition.  I routinely move between ALL
file systems using MAKE-PATHNAME and do not encounter problems.  If you
use :CASE :COMMON you can move smoothly between any file system.
If there is a bug somewhere in some implementation that is confusing you,
you need to cite a specific case in a specific implementation and version
that is causing you a problem.