1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! `Tcl_PkgProvideEx`, the stub slot, over the same registry the `package`
//! command uses.
//!
//! `Tk_Init`'s last act is to provide itself twice — as `Tk` and as `tk`, both
//! at `TK_PATCH_LEVEL`, both carrying `&tkStubs` as client data
//! (`tk9.0.4/generic/tkWindow.c:3461-3469`) — and it returns whatever the
//! second one returns. So this is the slot between a host and a `Tk_Init` that
//! completes, and the only interesting thing it can do is refuse: a second
//! provide of the same name at a different version is the one error path
//! (`generic/tclPkg.c:194-199`).
//!
//! Deciding "different" is not string inequality. Tcl normalises a version to a
//! space-separated list of signed integers first — `1.2a3` becomes
//! `1 0 2 -2 3`, so an alpha release sorts below the release it precedes
//! (`generic/tclPkg.c:1655-1747`) — and then compares those numbers segment by
//! segment as strings of equal length, which is what lifts the old 32-bit
//! ceiling on a version component (`generic/tclPkg.c:1778-1929`).
//!
//! Both of those, and the table they operate on, live in
//! [`crate::cmd_package`]: it is not behind the `tk` feature, and `package
//! vcompare` in an ordinary build needs the same arithmetic. That is also what
//! makes `package require Tk` in a script and Tk's own provide two doors onto
//! one registry rather than two registries that have to be kept in step.
use ;
use ;
use TCL_NAMES;
use host;
use ;
/// Every provided package as `(name, version)`, in the order it was provided.
///
/// The measurement this module exists to make: `Tk_Init` returning `TCL_OK`
/// and this list holding `Tk` and `tk` are the same fact seen from two sides.
/// The client data a package was provided with — `&tkStubs` for `tk`
/// (`tk9.0.4/generic/tkWindow.c:3466`).
/// The version ordering `Tcl_PkgProvideEx` decides "same version" with:
/// normalise both, then compare. `None` means one of them is not a version
/// number at all, which is the C's `TCL_ERROR` from `CheckVersionAndConvert`.
/// Slot 0: `int Tcl_PkgProvideEx(Tcl_Interp *, const char *, const char *,
/// const void *)` (`generic/tclPkg.c:154-200`).
///
/// # Safety
/// `name` and `version` must be NUL-terminated strings; `interp` must be a
/// `Tcl_Interp *` this crate handed out, or NULL.
pub unsafe extern "C"
/// Patch this module's slot into `t`, returning its index.
///
/// # Safety
/// The erased signature is the one `tclDecls.h` gives the slot, quoted on the
/// line above it.
pub unsafe
/// As [`host`]'s own installer: by name, never by literal index.
///
/// # Safety
/// `f` must have the signature `tclDecls.h` gives the named slot.
unsafe