#
Chapter 20
Windows Path Syntax

In general, a Windows pathname consists of an optional drive specifier and a drive-specific path. As noted in section 11.3, a Windows path can be absolute but still relative to the current drive; such paths start with a forward slash or backslash separator and are not UNC paths or paths that start with ``\``\`?`\``.

A path that starts with a drive specification is complete. Roughly, a drive specification is either a Roman letter followed by a colon, a UNC path of the form ``\``\`machine`\`volume`, or a ``\``\`?`\`` form followed by something other than `REL`\`element`. (Variants of ``\``\`?`\`` paths are described further below.)

MzScheme fails to implement the usual Windows path syntax in one way. Outside of MzScheme, a pathname `C:rant.txt` can be a drive-specific relative path. That is, it names a file `rant.txt` on drive `C:`, but the complete path to the file is determined by the current working directory for drive `C:`. MzScheme does not support drive-specific working directories (only a working directory across all drives, as reflected by the `current-directory` parameter; see section 7.9.1.1). Consequently, MzScheme implicitly converts a path like `C:rant.txt` into `C:`\`rant.txt`. More generally,

- MzScheme-specific: Whenever a path starts with a drive specifier `letter:` that is not followed by a forward slash or backslash, a backslash is inserted as the path is expanded.

Otherwise, MzScheme follows standard Windows path conventions, and MzScheme adds a ``\``\`?`\`REL` convention plus conventions to deal with excessive backslashes in ``\``\`?`\`` paths. In the following, `letter` stands for a Roman letter (case does not matter), `machine` stands for any sequence of characters that does not include backslashes or forward slashes and is not `?`, `volume` stands for any sequence of characters that does not include backslashes or forward slashes, and `element` stands for any sequence of characters that does not include backslashes.

- Trailing spaces and periods in a path element are ignored when the element is the last one in the path, unless the path starts with ``\``\`?`\`` or the element consists of only spaces and periods.

- The following special ``files'', which access devices, exist in all directories, case-insensitively, and with all possible endings after a period or colon, except in pathnames that start with ``\``\`?`\``: `NUL`, `CON`, `PRN`, `AUX`, `COM1`, `COM2`, `COM3`, `COM4`, `COM5`, `COM6`, `COM7`, `COM8`, `COM9`, `LPT1`, `LPT2`, `LPT3`, `LPT4`, `LPT5`, `LPT6`, `LPT7`, `LPT8`, `LPT9`.

- Except for ``\``\`?`\`` paths, forward slashes are equivalent to backslashes. Except for ``\``\`?`\`` paths and the start of UNC paths, multiple adjacent slashes and backslashes count as a single backslash. In a path that starts ``\``\`?`\`` paths, elements can be separated by either a single or double backslash.

- A directory can be accessed with or without a trailing separator. In the case of a non-``\``\`?`\`` path, the trailing separator can be any number of forward slashes and backslashes; in the case of a ``\``\`?`\`` path, a trailing separator must be a single backslash, except that two backslashes can follow ``\``\`?`\`letter:`.

- Except for ``\``\`?`\`` paths, a single period (`.`) as a path element means ``the current directory'', and a double period (`..`) as a path element means ``the parent directory.'' Up-directory path elements (i.e., `..`) immediately after a drive are ignored.

- A pathname that starts ``\``\`machine`\`volume` (where a forward slash can replace any backslash) is a UNC path, and the starting ``\``\`machine`\`volume` counts as the drive specifier.

- Normally, a path element cannot contain any of the following characters:

  ``

  < > : " / `\` |

  Except for backslash, path elements containing these characters can be accessed using a ``\``\`?`\`` path (assuming that the underlying filesystem allows the characters).

- In a pathname that starts ``\``\`?`\`letter:`\``, the ``\``\`?`\`letter:`\`` prefix counts as the path's drive, as long as the path does not both contain non-drive elements and end with two consecutive backslashes, and as long as the path contains no sequence of three or more backslashes. Forward slashes cannot be used in place of backslashes (but forward slashes can be used in element names, though the result generally does not name an actual directory or file).

- In a pathname that starts ``\``\`?`\`UNC`\`machine`\`volume`, the ``\``\`?`\`UNC`\`machine`\`volume` prefix counts as the path's drive, as long as the path does not end with two consecutive backslashes, and as long as the path contains no sequence of three or more backslashes. Two backslashes can appear in place of the backslash after `UNC` and/or the backslash after `machine`. The `UNC` part must be exactly the three uppercase letters, and forward slashes cannot be used in place of backslashes (but forward slashes can be used in element names).

- MzScheme-specific: A pathname that starts ``\``\`?`\`REL`\`element` or ``\``\`?`\`REL`\``\`element` is a relative path, as long as the path does not end with two consecutive backslashes, and as long as the path contains no sequence of three or more backslashes. This MzScheme-specific path form supports relative paths with elements that are not normally expressible in Windows paths (e.g., a final element that ends in a space). The `REL` part must be exactly the three uppercase letters, and forward slashes cannot be used in place of backslashes. If the path starts ``\``\`?`\`REL`\`..` then for as long as the path continues with reptitions of ``\`..`, each element counts as an up-directory element; a single backslash must be used to seperate the up-directory elements. As soon as a second backslash is used to separate the elements, or as soon as a non-`..` element is encountered, the remaining elements are all literals (never up-directory elements). When a ``\``\`?`\`REL` path value is converted to a string (or when the path value is written or displayed), the string does not contain the starting ``\``\`?`\`REL` or the immediately following backslashes; converting a path value to a byte string preserves the ``\``\`?`\`REL` prefix.

Three additional MzScheme-specific rules provide meanings to character sequences that are otherwise ill-formed as Windows paths:

- MzScheme-specific: In a pathname of the form ``\``\`?`\`any`\``\`` where `any` is any sequence of characters that does not start `letter:`, the entire path counts as the path's (non-existent) drive.

- MzScheme-specific: In a pathname of the form ``\``\`?`\`any`\``\``\`elements`, where `any` is any sequence of characters that does not start `letter:` and `elements` is any sequence that does not start with a backslash, does not end with two backslashes, and does not contain a sequence of three backslashes, the ``\``\`?`\`any`\``\``\`` part counts as the path's (non-existent) drive.

- MzScheme-specific: In a pathname that starts ``\``\`?`\`` and does not match either of the patterns from the preceding five bullets, ``\``\`?`\`` counts as the path's (non-existent) drive.

Outside of MzScheme, except for ``\``\`?`\`` paths, pathnames are typically limited to 259 characters. MzScheme internally converts pathnames to ``\``\`?`\`` form as needed to avoid this limit. The operating system cannot access files through ``\``\`?`\`` paths that are longer than 32,000 characters or so.

Where the above descriptions says ``character,'' substitute ``byte'' for interpreting byte strings as paths. The encoding of Windows paths into bytes preserves ASCII characters, and all special characters mentioned above are ASCII, so all of the rules are the same.

Beware that the backslash path separator is an escape character in MzScheme strings. Thus, the path ``\``\`?`\`REL`\`..`\``\`..` as a string must be written `"\\\\?\\REL\\..\\\\.."`.