Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#576 :case :common for logical pathnames.

closed-rejected
Bruno Haible
clisp (525)
5
2010-11-17
2010-11-16
No

When creating a logical pathname with make-pathname, :case :common, the pathname components are downcased.

I would argue that the customary case for logical pathnames is upper case, since:

19.3.1.1.7 Lowercase Letters in a Logical Pathname Namestring

When parsing words and wildcard-words, lowercase letters are translated to uppercase.

I'd expect (string= (pathname-name (make-pathname :host "TEST" :name "FILE" :type "DATA" :case :common))
(pathname-name #P"TEST:FILE.DATA"))
and of course (string= "FILE" (pathname-name #P"TEST:FILE.DATA"))
and similarly for the other pathname components.

[pjb@kuiper :0.0 ~]$ clisp -norc -ansi
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8

Welcome to GNU CLISP 2.49 (2010-07-07) <http://clisp.cons.org/>

Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2010

Type :h and hit Enter for context help.

[1]> (setf (logical-pathname-translations "TEST") nil)
NIL
[2]> (setf (logical-pathname-translations "TEST") (quote ((#P"TEST:**;*.*" "/tmp/**/*.*")
(#P"TEST:**;*" "/tmp/**/*"))))
((#P"TEST:**;*.*" "/tmp/**/*.*") (#P"TEST:**;*" "/tmp/**/*"))
[3]> (pathname-name (make-pathname :host "TEST" :name "FILE" :type "DATA" :case :common))
"file"
[4]> (pathname-name #P"TEST:FILE.DATA")
"FILE"
[5]>

Discussion

  • Bruno Haible
    Bruno Haible
    2010-11-17

    • status: open --> closed-rejected
     
  • Bruno Haible
    Bruno Haible
    2010-11-17

    The behaviour of :case :common is specified in CLHS section 19.2.2.1.2.2
    http://www.lispworks.com/documentation/HyperSpec/Body/19_bbabb.htm
    For clisp, the "filesystem's customary case" is lowercase, both on Unix and on Windows.

    The section you cite, 19.3.1.1.7, doesn't apply for two reasons:
    1) It applies only to logical pathnames. But
    (make-pathname :host "TEST" :name "FILE" :type "DATA" :case :common)
    yields an ordinary pathname in clisp. If you want a logical pathname, use the LOGICAL-PATHNAME function.
    2) It applies to the parsing of namestrings for logical pathnames
    that contain lowercase letters.
    In your example (make-pathname :host "TEST" :name "FILE" :type "DATA" :case :common)
    all of these are upper case, therefore the contents of 19.3.1.1.7 doesn't apply.

     
  • - I agree, I was wrong, 19.3.1.1.7 doesn't apply.

    - make-pathname creates a logical pathname when the :host parameter is
    a logical host, in clisp, as in any conforming implementation.

    - I was also wrong with:
    (pathname-name (make-pathname :host "TEST" :name "FILE" :type "DATA" :case :common))
    it should indeed return "file"; this is correctly implemented in clisp.

    - but the other form, (pathname-name #P"TEST:FILE.DATA") should return
    "file", not "FILE", because by default the :case parameter of
    pathname-name is :local, and "19.2.2.1.2.2 Common Case in Pathname
    Components" mentions that round trip should be information
    preserving (including case for local pathnames).

    Actually there are other problems. In an implementation where the
    customary case is lower case, the pathname accessors cannot return the
    same case with and without :case :common, but this is what clisp does:

    CL-USER> (print-pathname (make-pathname :host "LOGICAL" :device :unspecific :directory '(:absolute "DIR" "SUBDIR") :name "NAME" :type "DATA" :version nil :case :common))

    LOGICAL-PATHNAME #P"LOGICAL:dir;subdir;name.data"
    -------------------- :case :local (default)
    Host : "LOGICAL"
    Device : :UNSPECIFIC
    Directory : (:ABSOLUTE "dir" "subdir")
    Name : "name"
    Type : "data"
    Version : NIL
    -------------------- :case :common
    Host : "LOGICAL"
    Device : :UNSPECIFIC
    Directory : (:ABSOLUTE "dir" "subdir")
    Name : "name"
    Type : "data"
    Version : NIL
    --------------------
    #P"LOGICAL:dir;subdir;name.data"
    CL-USER> (print-pathname #P"LOGICAL:dir;subdir;name.data")

    LOGICAL-PATHNAME #P"LOGICAL:DIR;SUBDIR;NAME.DATA"
    -------------------- :case :local (default)
    Host : "LOGICAL"
    Device : :UNSPECIFIC
    Directory : (:ABSOLUTE "DIR" "SUBDIR")
    Name : "NAME"
    Type : "DATA"
    Version : NIL
    -------------------- :case :common
    Host : "LOGICAL"
    Device : :UNSPECIFIC
    Directory : (:ABSOLUTE "DIR" "SUBDIR")
    Name : "NAME"
    Type : "DATA"
    Version : NIL
    --------------------
    #P"LOGICAL:DIR;SUBDIR;NAME.DATA"
    CL-USER> (print-pathname #P"LOGICAL:DIR;SUBDIR;NAME.DATA")

    LOGICAL-PATHNAME #P"LOGICAL:DIR;SUBDIR;NAME.DATA"
    -------------------- :case :local (default)
    Host : "LOGICAL"
    Device : :UNSPECIFIC
    Directory : (:ABSOLUTE "DIR" "SUBDIR")
    Name : "NAME"
    Type : "DATA"
    Version : NIL
    -------------------- :case :common
    Host : "LOGICAL"
    Device : :UNSPECIFIC
    Directory : (:ABSOLUTE "DIR" "SUBDIR")
    Name : "NAME"
    Type : "DATA"
    Version : NIL
    --------------------
    #P"LOGICAL:DIR;SUBDIR;NAME.DATA"

    There is also the problem that the result of:
    (make-pathname :host "LOGICAL" :device :unspecific :directory '(:absolute "DIR" "SUBDIR") :name "NAME" :type "DATA" :version nil :case :common)
    is printed as #P"LOGICAL:dir;subdir;name.data".

    It should be printed using the logical pathname syntax, that is, in
    upper case, because:

    1- it is a logical pathname,

    2- its printed form should be readable as the 'same' logical pathname,
    that is, a pathname with the same components,

    3- #P gives the string to parse-namestring, without addionnal
    argument, therefore :host is nil, and in this case, for the string
    to be parsed as a logical pathname, it needs to have the logical
    pathname syntax, which takes only upper case letters.

    4- when reading back this lowercase form, we don't read the same
    pathname as originally returned by the make-pathname form.

     
  • I forgot the definition of print-pathname:

    (defun print-pathname (pathname)
    (format t "~%~A ~S~%" (type-of pathname) pathname)
    (format t "-------------------- :case :local (default)~%")
    (format t "~&~{~{~@(~9A~) : ~S~&~}~}"
    (mapcar (lambda (name field) (list name (funcall field pathname)))
    '(host device directory name type version)
    '(pathname-host pathname-device pathname-directory
    pathname-name pathname-type pathname-version)))
    (format t "-------------------- :case :common~%")
    (format t "~&~{~{~@(~9A~) : ~S~&~}~}"
    (mapcar (lambda (name field arguments) (list name (apply field pathname arguments)))
    '(host device directory name type version)
    '(pathname-host pathname-device pathname-directory
    pathname-name pathname-type pathname-version)
    '((:case :common) (:case :common) (:case :common)
    (:case :common) (:case :common) ())))
    (format t "-------------------- ~%")
    pathname)