Subject: [clisp-list] logical-pathname

From: Pascal Bourguignon <[email-masked]>
Date: Tue Jan 28 20:28:04 2003

Hello,

[37]> (lisp-implementation-version)
"2.30 (released 2002-09-15) (built 3251450717) (memory 3251450977)"

I'm wondering if there is not a problem with logical-pathname on unix:

[38]> (namestring (pathname "/home/pascal/tmp/test/*"))
"/home/pascal/tmp/test/*"

OK.

[39]> (namestring (logical-pathname "/home/pascal/tmp/test/*"))
";HOME;PASCAL;TMP;TEST;*"

Oops !  A relative path!

[40]> (logical-pathname "/home/pascal/tmp/test/*")
#S(LOGICAL-PATHNAME :HOST NIL :DEVICE NIL
   :DIRECTORY (:RELATIVE "HOME" "PASCAL" "TMP" "TEST") :NAME :WILD :TYPE NIL
   :VERSION NIL)

Since the namestring started with '/', I expected an :ABSOLUTE logical
path name.

As  it  is, the  :RELATIVE  logical-pathname  can't  be used,  because
DIRECTORY really works relatively  to the current directory instead of
relatively to the root:

[41]> (directory (logical-pathname "/home/pascal/tmp/test/*"))
NIL

[42]> (directory (pathname "/home/pascal/tmp/test/*"))
(#P"/home/pascal/tmp/test/a"
 #P"/home/pascal/tmp/test/b"
 #P"/home/pascal/tmp/test/c")

Note  also  the  dot  appended  to  the  pathname  when  translating  a
logical-path name:

(translate-logical-pathname "/home/pascal/tmp/test/*")
#P"home/pascal/tmp/test/*."

could prevent DIRECTORY to work too even if the logical path built was
:ABSOLUTE.

[150]> (directory #P"/home/pascal/tmp/test/*.")
NIL
[151]> (directory #P"/home/pascal/tmp/test/*")
(#P"/home/pascal/tmp/test/a"
 #P"/home/pascal/tmp/test/b"
 #P"/home/pascal/tmp/test/c")

The paths  in Common-Lisp is  already complicated enough. It  would be
nice if the implementation showed a little more regularity there.

If I've understood correctly the section 19.4 of CLHS and the relative
glossary entries, we have the following "class diagram" anontated with
transitions denoting the functions available to manipulate the paths.

Please correct me if I've misunderstood a specification here.

   (Perhaps, pathname and physical-pathname are identical?)

                              parse-namestring
                                   +--+
                                   |  |
                                   V  |
                     +------------------------+
                     |        pathname        |---------------------------+
                     +------------------------+                           |
      make-pathname  | + device               |                           |
   *---------------->| + directory            |                           |
                     | + host                 |<----------------------+   |
                     | + name                 |                       |   |
                     | + type                 |                       |   |
                     | + version              |                       |   |
                     +------------------------+                       |   |
                                  |                                   |   |
                                 / \                                  |   |
        logical-pathname        /___\                                 |   |
              +--+                |                                   |   |
              |  |    +-----------+-------------+                     |   |
              V  |    |                         |                     |   |
             +------------------+      +-------------------+          |   |
    +------->| logical-pathname |      | physical-pathname |          |   |
    |        +------------------+      +-------------------+          |   |
    |                                                  ^              |   |
    |                     translate-logical-pathname   |              |   |
    |                             +--------------------+              |   |
    |                             |                                   |   |
    |                             |                                   |   |
    |logical-pathname             |                                   |   |
    |                             |             parse-namestring      |   |
    |            +---------------------+           pathname           |   |
    +------------| pathname-designator |------------------------------+   |
                 +---------------------+                                  |
                            |                                             |
                           / \                                            |
                          /___\                   enough-namestring       |
                            |                       host-namestring       |
                +-----------+----------+           directory-namestring   |
                |                      |              file-namestring     |
             +--------+         +------------+          namestring        |
             | stream |         | namestring |<---------------------------+
             +--------+         +------------+
                                       |
                                      / \
                                     /___\
                                       |
                          +------------+---------------+
                          |                            |
               +---------------------+      +-----------------------+
               | string-standardized |      | string-implementation |
               +---------------------+      +-----------------------+
          aka logical-pathname-namestring

Standardized  string and logical  pathname namestring  seem to  be the
same thing.   Then pathname should  probably build a  logical pathname
when  given  a  logical  pathname  namestring contrarily  to  what  is
currently implemented.

Note also  about pathname  that it's specified  over a pathspec,  ie a
pathname designator,  (stream or  namestring), not over  pathname. So:
(pathname (pathname "/tmp")) should probably raise an error instead of
returning (pathname "/tmp")...

--
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
There is a fault in reality. Do not adjust your minds. -- Salman Rushdie

---

From: Peter Seibel <[email-masked]>
Date: Wed Jan 29 06:36:32 2003

> returning (pathname "/tmp")...

Why isn't a pathname a pathname designator: 

Hmmm. My CLHS glossary says:

  pathname designator n. a designator for a pathname; that is, an
  object that denotes a pathname and that is one of: a pathname
  namestring (denoting the corresponding pathname), a stream
  associated with a file (denoting the pathname used to open the file;
  this may be, but is not required to be, the actual name of the
  file), or a pathname (denoting itself). See Section 21.1.1.1.2 (Open
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  and Closed Streams).

-Peter

-- 
Peter Seibel
[email-masked]

---

From: Sam Steingold <[email-masked]>
Date: Wed Jan 29 07:19:08 2003

> * In message <[email-masked]>
> * On the subject of "[clisp-list] logical-pathname"
> * Sent on Wed, 29 Jan 2003 05:27:32 +0100 (CET)
> * Honorable Pascal Bourguignon <[email-masked]> writes:
>

what did you expect?!
when forced to consider a path as logical, CLISP treats #\/ as #\;.
otherwise it would have to signal an error because #\/ is not a valid
logical pathname char.

>    :DIRECTORY (:RELATIVE "HOME" "PASCAL" "TMP" "TEST") :NAME :WILD :TYPE NIL

yep.

> Since the namestring started with '/', I expected an :ABSOLUTE logical

why?  ";foo;bar" is relative.

>  #P"/home/pascal/tmp/test/c")

correct.

> nice if the implementation showed a little more regularity there.

just do not ask your implementation to treat physical pathnames as
logical ones and vv.

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
Man has 2 states: hungry/angry and sate/sleepy.  Catch him in transition.

---

From: Pascal Bourguignon <[email-masked]>
Date: Wed Jan 29 10:21:04 2003

>   file), or a pathname (denoting itself). See Section 21.1.1.1.2 (Open

Yes, I missed this clause. Thank you.

So that gives (I'll reorder the boxes later):

+-------------------------+   
|                         |                     
|                    +------------------------+
|                    |        pathname        |---------------------------+
|                    +------------------------+                           |
|     make-pathname  | + device               |                           |
|  *---------------->| + directory            |                           |
|                    | + host                 |<----------------------+   |
|                    | + name                 |                       |   |
|                    | + type                 |                       |   |
|                    | + version              |                       |   |
|                    +------------------------+                       |   |
|                                 |                                   |   |
|                                / \                                  |   |
|                               /___\                                 |   |
|                                 |                                   |   |
|                     +-----------+-------------+                     |   |
|                     |                         |                     |   |
|            +------------------+      +-------------------+          |   |
|   +------->| logical-pathname |      | physical-pathname |          |   |
|   |        +------------------+      +-------------------+          |   |
|   |                                                  ^              |   |
|   |                     translate-logical-pathname   |              |   |
|   |                             +--------------------+              |   |
|   |                             |                                   |   |
|   |                             |                                   |   |
|   |logical-pathname             |                                   |   |
|   |                             |             parse-namestring      |   |
|   |            +---------------------+           pathname           |   |
|   +------------| pathname-designator |------------------------------+   |
|                +---------------------+                                  |
|                           |                                             |
|                          / \                                            |
|                         /___\                   enough-namestring       |
|                           |                       host-namestring       |
+---------------+-----------+----------+           directory-namestring   |
                |                      |              file-namestring     |
             +--------+         +------------+          namestring        |
             | stream |         | namestring |<---------------------------+
             +--------+         +------------+
                                       |
                                      / \
                                     /___\
                                       |
                          +------------+---------------+
                          |                            |
               +---------------------+      +-----------------------+
               | string-standardized |      | string-implementation |
               +---------------------+      +-----------------------+
          aka logical-pathname-namestring

---

From: Sam Steingold <[email-masked]>
Date: Wed Jan 29 11:16:04 2003

> * In message <[email-masked]>
> * On the subject of "Re: [clisp-list] logical-pathname"
> * Sent on Wed, 29 Jan 2003 19:51:34 +0100
> Sam Steingold writes:
> I'm not alone expecting an absolute path here.  The CLISP
> implementation notes too:
> 
>      : / denotes absolute pathnames        <----------------

in physical pathnames.

> It seems obvious to me that applying directory to the same namestring
> converted either to pathname or to logical-pathname should give the
> same result.

why?

logical pathnames are quite different from physical ones.
to begin with, "/foo/bar" is __NOT__ a valid logical pathname
namestring in ANSI CL.
CLISP, as an __EXTENSION__, treats it as if it were ";foo;bar".
I am not sure it would be better to treat it as "foo;bar".

do the users really think that the latter is better?

(note that it is not clear that this extension is useful at all: it is a
big mistake of judgment to mix logical and physical pathnames)

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
In every non-trivial program there is at least one bug.

---

From: Marco Antoniotti <[email-masked]>
Date: Wed Jan 29 11:32:04 2003

On Wednesday, Jan 29, 2003, at 14:17 America/New_York, Sam Steingold 

> CLISP, as an __EXTENSION__, treats it as if it were ";foo;bar".

This extension is non conforming.  See CLHS for LOGICAL-PATHNAME.

> big mistake of judgment to mix logical and physical pathnames)

I think CLisp should signal an error if LOGICAL-PATHNAME is passed a 
non logical pathname namestring.

This would make it conforming and will allow you to write (more) 
portable code.

I agree that mixing logical and non logical namestrings is fishy.

Cheers

--
Marco Antoniotti
NYU Courant Bioinformatics Group		tel. +1 - 212 - 998 3488
715 Broadway 10th FL				fax. +1 - 212 - 998 3484
New York, NY, 10003, U.S.A.

---

From: Pascal Bourguignon <[email-masked]>
Date: Wed Jan 29 11:40:04 2003

Marco Antoniotti writes:
> 
> The following discussion is moot since
> 
> is not a logical pathname designator.

pathspec---a logical pathname, a logical pathname namestring, or a stream.

Oops, you're right.  
 
> This is a bug in CLisp, as it should signal an error, as per CLHS 
> definition of the function LOGICAL-PATHNAME.
> 
> You may argue that the CLHS is bogus here, but that is a totally 
> different issue.

Unfortunately, I hoped that it was only an implementation issue. 

I note that logical-pathname takes a stream too, and that a stream can
be obtained from a pathname designator.

So,  I suppose  that  the only  Common-Lisp  compatible way  to get  a
logical-pathname from an implementation dependant string is with:

(let ((already-existed (open "/home/pascal/tmp/test/file" :direction :proble)))
  (prog1  (logical-pathname (open "/home/pascal/tmp/test/file" 
                                 :direction :read
                                 :if-does-not-exist :create))
          (unless already-existed (delete-file "/home/pascal/tmp/test/file"))))

and this  works only for files and  when we have access  rights to the
directory.  Anything else simplier?

Well, once  more I  notice useless features  in Common-Lisp,  that is,
features so  ill-defined that you have  to write your  own. I'll parse
namestrings myself and build pathnames by hand.

Updated diagram:

I notice  that there is  no way to  get a logical-pathname but  from a
logicial-pathname-namestring. Is that correct?

   translate-logical-pathname
   parse-namestring
   pathname            +---------------------+
   +-------------------| pathname-designator |
   |                   +---------------------+
   |  *                          |
   |  |make-pathname            / \
   |  |                        /___\
   |  |                          |
   |  |  +----------------+------+---------------+
   V  V  |                |                      |
  +--------------+    +--------+          +------------+
  |   pathname   |    | stream |          | namestring |
  +--------------+    +--------+          +------------+
  | + device     |        |                   ^    |
  | + directory  |        |  namestring       |    |
  | + host       |----------------------------+    |
  | + name       |        |  directory-namestring  |
  | + type       |        |  enought-namestring   / \
  | + version    |        |  host-namestring     /___\
  +--------------+        |  file-namestring       |
         |                |                        |  +-----------------------+
        / \               |                        +--| string-implementation |
       /___\              |                        |  +-----------------------+
         |                |                        |
+------------------+      V logical-pathname    +-----------------------------+
| logical-pathname |<---------------------------| logical-pathname-namestring |
+------------------+      ^                     +-----------------------------+
              |           |
              +-----------+

---

From: Marco Antoniotti <[email-masked]>
Date: Wed Jan 29 12:02:02 2003

On Wednesday, Jan 29, 2003, at 14:38 America/New_York, Pascal 

> directory.  Anything else simplier?

No.  AFAIU Even the above would not work.  Check the spec for the 
function LOGICAL-PATHNAME.

In the example above OPEN will return a PATHNAME not a 
LOGICAL-PATHNAME.  Hence you cannot use LOGICAL-PATHNAME as you hope do 
do.

In CL the process of translating a logical pathname is unidirectional 
and not reversible.  Which is what it seems you are trying to do.

> namestrings myself and build pathnames by hand.

That is exactly the wrong approach.  The pathname stuff in CL is 
difficult and sometime non univocally defined, but it works.

What exactly are you trying to do?

Note that your main entry points in the CL pathname subsystem are 
PARSE-NAMESTRING and LOGICAL-PATHNAME-TRANSLATIONS.

If you stick to these you will solve most of your problems.

	...
> logicial-pathname-namestring. Is that correct?

Yes (or from another logical pathname, or a stream with an associated 
logical pathname).

Cheers

---

From: Pascal Bourguignon <[email-masked]>
Date: Wed Jan 29 12:11:10 2003

> to begin with, "/foo/bar" is __NOT__ a valid logical pathname

In effect. I overlooked that.

> I am not sure it would be better to treat it as "foo;bar".

The fact  is that such behavior  should not be depended  upon. I guess
that in these  cases, it's better to raise an  error.  That would help
the   programmers   to  avoid   lock   themselves  into   incompatible
idiosyncrasies.

> big mistake of judgment to mix logical and physical pathnames)

Writting a program, I have unix path strings (and regexp wildcards) in
the configuration. I wanted to "abstract" them to ease portability and
thus convert  them to logical paths  and only use logical  path in the
rest of the program.

Well, it appears that logical  pathnames are read only (can't generate
a logical path name from a given configuration.  At most I can convert
my  unix paths  to (physical)  pathnames.   Since I  can't convert  to
logical  pathnames,  I'd  better  manipulate  the  unix  path  strings
directly (pathname  wildcard is too  restricted) or thru  the pathname
and forget logical pathnames.

---

From: Marco Antoniotti <[email-masked]>
Date: Wed Jan 29 12:16:22 2003

> logicial-pathname-namestring. Is that correct?

Just to make another argument about this.

Suppose you have

    (setf (logical-pathname-translations "FOO")
       `(("**;*.*" "/usr/foo/*.*")))

    (setf (logical-pathname-translations "GNAO")
       `(("**;*.*" "/usr/foo/*.*")))

The above is legal CL.  Now you do

   (translate-logical-pathname "FOO:qwe;rty.c")
    ==> #p"/usr/foo/rty.c"

   (translate-logical-pathname "GNAO:qwe;rty.c")
    ==> #p"/usr/foo/rty.c"

The question now is: what should the hypothetical

	(get-logical-pathname-from-namestring "/usr/foo/rty.c")

return?

Note that there are ways in CL to build a function that would return 
all the possible logical pathnames from an arbitrary pathname 
namestring.  This involves keeping track of all the defined logical 
hosts and building a match with all possible translations.

This is left as an easy exercise to the reader :)

Jokes apart, what are you trying to do?

Cheers

---

From: Marco Antoniotti <[email-masked]>
Date: Wed Jan 29 12:38:03 2003

On Wednesday, Jan 29, 2003, at 15:08 America/New_York, Pascal 
> thus convert  them to logical paths  and only use logical  path in the

Note that AFAIK, in any UNIX system it is very difficult to reliably 
specify something like

	(make-pathname :directory '(:relative "foo" :wild-inferiors "bar"))

> and forget logical pathnames.

Noooooo.  DO NOT DO THAT! Check out PARSE-NAMESTRING.  If you have a 
"configuration" somewhere, it means that that is something you are 
loading up at start time.  This means that you are better off setting 
up logical pathname translations to start with.

Cheers