Artifact [3c6ca763bf]

Login

Artifact 3c6ca763bf8281e2be678a748fb133dd8e1bdccb786c1e06f6ae4cc117c25f18:


# TIP 595: Unicode-aware/case-sensitive Loadable Library handling
	Author:         Jan Nijtmans <[email protected]>
	State:          Final
	Type:           Project
	Vote:           Done
	Tcl-Version:    9.0
	Tcl-Branch:     bug-ea39ab591e
	Vote-Summary:	Accepted 7/0/1
	Votes-For:	AK, DP, JN, KW, KK, MC, SL
	Votes-Against:	none
	Votes-Present:	FV
-----
# Abstract

The "load" command, and its supporting C API is quite misleading. For example
the 3th argument of "load" is case-insensitive: It is converted to Titlecase,
(ASCII-only), then `_Init` is attached to it, then the C-function in the
shared library with this name is called. No package handling is done,
still the 3th argument of "load" is called "packageName".

See also bug report [ea39ab591e](https://core.tcl-lang.org/tcl/info/ea39ab591e):
<b>Tcl_StaticPackage allows case sensitvity; [load] prevents it</b> which
describes in better wordings what's wrong.

This TIP proposes to get rid of the case-insensitivity of the "load"
command, except in the guessing of the `prefix` from the filename.
In order to distinguish libraries from packages (libraries are
available globally while package are per interpreter), a number
of renamings will be done.

# Specification

In Tcl 8.7, rename `Tcl_StaticPackage` to `Tcl_StaticLibrary`,
`Tcl_PackageInitProc` to `Tcl_LibraryInitProc` and `Tcl_PackageUnloadProc`
to `Tcl_LibraryUnloadProc`. Also add the following defines in `tcl.h`:
<pre>
    #define Tcl\_PackageInitProc Tcl\_LibraryInitProc
    #define Tcl\_PackageUnloadProc Tcl\_LibraryUnloadProc
    #define Tcl\_StaticPackage Tcl\_StaticLibrary
</pre>
This way, the new names of the functions already can be used
in Tcl 8.7, but the functionality stays the same. Hopefully
those new names make it clear that those functions take
part in the `load` mechanism, not the `package` mechanism.

In Tcl 9.0, if the "load" command's 3th parameter is missing,
this parameter is guessed from the filename. Starting with
Tcl 9.0, a Unicode Titlecase will be used, not a ASCII one.
The full algorithm becomes:

  * If the filename starts with `lib`, strip it.
  * If the filename then starts with `tcl9`, strip it.
  * Take the characters following that, up to (but not including) the
    first character which is a (Unicode) digit or not a (Unicode) word.
  * Convert those characters to (Unicode) Titlecase.
  * The result will be the guessed `prefix` parameter.

This is almost the same as the Tcl 8.x algorithm, the enhancement is that
the characters used in the filename are no longer limited to ASCII. For
example, a shared library `libπ.so` will result in a prefix `Π`, so the
initialization function `Π_Init()` will be called when loading this file.

When using Tcl 9.0, the following existing library names will be changed:

  * `tcldde14.dll` -> `tcl9dde14.dll`
  * `tclregistry13.dll` -> `tcl9registry13.dll`
  * `tk87.dll` -> `tcl9tk87.dll` (on Windows)
  * `libtk8.7.so` -> `libtcl9tk8.7.so` (on UNIX)

This makes it possible to install Tk 8.7 in the same
directory when compiled for Tcl 8.7 resp 9.0. Since
the filename is different, the pkgIndex.tcl file can
load the correct Tk library no matter Tcl 8.7 or 9.0
is doing the call. (Of course, Tk 8.7 needs to be
compiled twice then, once with Tcl 8.7 headers, once
with Tcl 9.0 headers)

# Implementation

Implementation is in Tcl (and Tk) branch bug-ea39ab591e.

# Compatibility

This is not compatible with Tcl 8.x, but there is a simple way to
make code compatible with both Tcl 8.x and 9.0: Just replace
all "load" invocations:

  * `load <fileName> <prefix> ?<interp>?`

by

  * `load <fileName> [string totitle <prefix>] ?<interp>?`

.

Of course, if the 3th argument of `load` already is in Titlecase
(it usually is) nothing needs to be done.

# Copyright

This document has been placed in the public domain.