Tcl Library Source Code

Check-in [aeb3bec0da]
Login
Bounty program for improvements to Tcl and certain Tcl packages.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:virtchannel-base, tcl::chan::cat - Tkt [1975182bdd] Fixed non-functional event handling of the channel. Version bump 1.0.3 - B (tcl::chan::cat) - T (tcl::chan::cat, NEW)
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: aeb3bec0da51bae5057e5e32e71c9551e6982e2c8fc0f90bcd51206ced87fc0a
User & Date: aku 2019-04-15 19:22:54
Original Comment: virtchannel-base, tcl::chan::cat - Tkt [1975182bdd] Version bump 1.0.3 - B (tcl::chan::cat) - T (tcl::chan::cat, NEW)
References
2019-04-15
19:23 Closed ticket [1975182bdd]: tcl::chan::cat - syntax error and bad behavior with fileevents plus 6 other changes artifact: 8e8ecf4369 user: aku
Context
2019-04-15
23:13
Zip - Mkzip - Tkt [b9725d990b] Fix handling of directories with leading dash ('-') in their name. Version bump 1.2.1 - B (mkzip) - T (mkzip, NEW) check-in: 5f3611f96a user: aku tags: trunk
19:22
virtchannel-base, tcl::chan::cat - Tkt [1975182bdd] Fixed non-functional event handling of the channel. Version bump 1.0.3 - B (tcl::chan::cat) - T (tcl::chan::cat, NEW) check-in: aeb3bec0da user: aku tags: trunk
2019-04-13
03:36
struct / struct::graph - Tkt [5edaf187fa] - Reworked the internal `CheckE` validation command for node filtering to treat words with a leading dash after -in, etc. as node names instead of invalid options, until a valid option is seen again, or the end of the command is reached, whichever comes first. This behaviour is now documented. Version bump 2.4.2 - (B) struct::graph - (T) struct::graph - (D) struct::graph check-in: bb9e30207b user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to embedded/md/tcllib/files/modules/virtchannel_base/cat.md.

1
2
3
4
5
6
7
8
9
10
11
12
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[//000000001]: # (tcl::chan::cat \- Reflected/virtual channel support)
[//000000002]: # (Generated from file 'cat\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2011 Andreas Kupries <andreas\[email protected]\.sourceforge\.net>)
[//000000004]: # (tcl::chan::cat\(n\) 1 tcllib "Reflected/virtual channel support")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
................................................................................
  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require TclOO  
package require tcl::chan::core ?1?  
package require tcl::chan::cat ?1?  

[__::tcl::chan::cat__ *chan*\.\.\.](#1)  

# <a name='description'></a>DESCRIPTION

The __tcl::chan::cat__ package provides a command creating concatenation
channels\. These are non\-seekable channels owning a list of subordinate channels



|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[//000000001]: # (tcl::chan::cat \- Reflected/virtual channel support)
[//000000002]: # (Generated from file 'cat\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2011 Andreas Kupries <andreas\[email protected]\.sourceforge\.net>)
[//000000004]: # (tcl::chan::cat\(n\) 1\.0\.3 tcllib "Reflected/virtual channel support")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
................................................................................
  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require TclOO  
package require tcl::chan::core ?1?  
package require tcl::chan::cat ?1\.0\.3?  

[__::tcl::chan::cat__ *chan*\.\.\.](#1)  

# <a name='description'></a>DESCRIPTION

The __tcl::chan::cat__ package provides a command creating concatenation
channels\. These are non\-seekable channels owning a list of subordinate channels

Changes to idoc/man/files/modules/virtchannel_base/cat.n.

1
2
3
4
5
6
7
8
9
10
11
12
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
'\"
'\" Generated from file 'cat\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2011 Andreas Kupries <[email protected]\&.sourceforge\&.net>
'\"
.TH "tcl::chan::cat" n 1 tcllib "Reflected/virtual channel support"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
................................................................................
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBTclOO \fR
.sp
package require \fBtcl::chan::core  ?1?\fR
.sp
package require \fBtcl::chan::cat  ?1?\fR
.sp
\fB::tcl::chan::cat\fR \fIchan\fR\&.\&.\&.
.sp
.BE
.SH DESCRIPTION
.PP
The \fBtcl::chan::cat\fR package provides a command creating



|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
'\"
'\" Generated from file 'cat\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2011 Andreas Kupries <[email protected]\&.sourceforge\&.net>
'\"
.TH "tcl::chan::cat" n 1\&.0\&.3 tcllib "Reflected/virtual channel support"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
................................................................................
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBTclOO \fR
.sp
package require \fBtcl::chan::core  ?1?\fR
.sp
package require \fBtcl::chan::cat  ?1\&.0\&.3?\fR
.sp
\fB::tcl::chan::cat\fR \fIchan\fR\&.\&.\&.
.sp
.BE
.SH DESCRIPTION
.PP
The \fBtcl::chan::cat\fR package provides a command creating

Changes to idoc/www/tcllib/files/modules/virtchannel_base/cat.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcl::chan::cat(n) 1 tcllib &quot;Reflected/virtual channel support&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcl::chan::cat - Concatenation channel</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
................................................................................
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">TclOO</b></li>
<li>package require <b class="pkgname">tcl::chan::core <span class="opt">?1?</span></b></li>
<li>package require <b class="pkgname">tcl::chan::cat <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::tcl::chan::cat</b> <i class="arg">chan</i>...</a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>






|







 







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcl::chan::cat(n) 1.0.3 tcllib &quot;Reflected/virtual channel support&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcl::chan::cat - Concatenation channel</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
................................................................................
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">TclOO</b></li>
<li>package require <b class="pkgname">tcl::chan::core <span class="opt">?1?</span></b></li>
<li>package require <b class="pkgname">tcl::chan::cat <span class="opt">?1.0.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::tcl::chan::cat</b> <i class="arg">chan</i>...</a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>

Changes to modules/virtchannel_base/ChangeLog.





1
2
3
4
5
6
7



2013-12-17  Andreas Kupries  <[email protected]>

	* randseed.man: Fixed package name.

2013-11-22  Andreas Kupries  <[email protected]>

	* memchan.tcl (Events): Ticket [864a0c83e3]. Do not suppress
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
2019-03-12  Aldo Buratti

    * cat.tcl - BUGFIX in event-handling . Version bumped to 1.0.3
    * 
2013-12-17  Andreas Kupries  <[email protected]>

	* randseed.man: Fixed package name.

2013-11-22  Andreas Kupries  <[email protected]>

	* memchan.tcl (Events): Ticket [864a0c83e3]. Do not suppress

Changes to modules/virtchannel_base/cat.man.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[comment {-*- tcl -*- doctools manpage}]

[manpage_begin tcl::chan::cat n 1]
[keywords {concatenation channel}]
[keywords {reflected channel}]
[keywords {tip 219}]
[keywords {virtual channel}]
[copyright {2011 Andreas Kupries <[email protected]>}]
[moddesc   {Reflected/virtual channel support}]
[category  Channels]
[titledesc {Concatenation channel}]
[require Tcl 8.5]
[require TclOO]
[require tcl::chan::core [opt 1]]
[require tcl::chan::cat [opt 1]]
[description]
[para]

The [package tcl::chan::cat] package provides a command creating
concatenation channels. These are non-seekable channels owning a list
of subordinate channels whose contents they return in order, until all
are exhausted. In this manner the channel is the concatentation of the
>
|











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[comment {-*- tcl -*- doctools manpage}]
[vset Version 1.0.3]
[manpage_begin tcl::chan::cat n [vset Version]]
[keywords {concatenation channel}]
[keywords {reflected channel}]
[keywords {tip 219}]
[keywords {virtual channel}]
[copyright {2011 Andreas Kupries <[email protected]>}]
[moddesc   {Reflected/virtual channel support}]
[category  Channels]
[titledesc {Concatenation channel}]
[require Tcl 8.5]
[require TclOO]
[require tcl::chan::core [opt 1]]
[require tcl::chan::cat [opt [vset Version]]]
[description]
[para]

The [package tcl::chan::cat] package provides a command creating
concatenation channels. These are non-seekable channels owning a list
of subordinate channels whose contents they return in order, until all
are exhausted. In this manner the channel is the concatentation of the

Changes to modules/virtchannel_base/cat.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
..
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
...
104
105
106
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133
134
135
136
137
138
139
# -*- tcl -*-
# # ## ### ##### ######## #############
# (C) 2011 Andreas Kupries

# Facade concatenating the contents of the channels it was constructed
# with. Owns the sub-ordinate channels and closes them on exhaustion and/or
# when closed itself.

# @@ Meta Begin
# Package tcl::chan::cat 1.0.1
# Meta as::author {Andreas Kupries}
# Meta as::copyright 2011
# Meta as::license BSD
# Meta description Facade concatenating the contents of the channels it
# Meta description was constructed with. Owns the sub-ordinate channels
# Meta description and closes them on exhaustion and/or when closed itself.
# Meta platform tcl
................................................................................

    # We are not using the standard event handling class, because here
    # it will not be timer-driven. We propagate anything related to
    # events to catin and catout instead and let them handle things.

    constructor {args} {
	set channels $args
	# Disable encoding and translation processing in the wrapped channels.
	# This will happen in our generic layer instead.
	foreach c $channels {
	    fconfigure $c -translation binary
	    fconfigure $c -translation binary
	}
	set delay 10
	set watching 0
	return
    }

................................................................................
    method watch {c requestmask} {
	if {"read" in $requestmask} {
	    # Activate event handling.  Either drive an eof home via
	    # timers, or activate things in the foremost sub-ordinate.

	    set watching 1
	    if {![llength $channels]} {
		set timer [after $delay \
			       [namespace code [list my Post $c]]]
	    } else {
		set c [lindex $channels 0]
		fileevent readable $c [list chan postevent $c read]
	    }
	} else {
	    # Stop events. Kill timer, or disable in the foremost
	    # sub-ordinate.

	    set watching 0
	    if {![llength $channels]} {
		catch { after cancel $timer }
	    } else {
		fileevent readable [lindex $channels 0] {}
	    }
	}
	return
    }

    method read {c n} {
	if {![llength $channels]} {
	    # Actually should be EOF signal.
	    return {}
	}

	set buf {}
	while {([string length $buf] < $n) &&
	       [llength $channels]} {

................................................................................
	    set toread [expr {$n - [string length $buf]}]
	    append buf [::read $in $toread]

	    if {[eof $in]} {
		close $in
		set channels [lrange $channels 1 end]

		# The close above also killed any fileevent handling
		# we might have attached to this channel. We may have
		# to update the settings (i.e. move to next channel,
		# or to timer-based, to drive the eof home).


		if {$watching} {
		    my watch $c read
		}
	    }
	}

	if {$buf eq {}} {
	    return -code error EAGAIN
	}


	return $buf
    }

    method Post {c} {
	set timer [after $delay \
		       [namespace code [list my Post $c]]]
	chan postevent $c read
	return
    }
}

# # ## ### ##### ######## #############
package provide tcl::chan::cat 1.0.2
return

|






|







 







|


<







 







<
|

|
<


|
|





|







|







 







|
|
|
|
>







|
|
<
<
>




<
|






|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
..
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
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121


122
123
124
125
126

127
128
129
130
131
132
133
134
135
# -*- tcl -*-
# # ## ### ##### ######## #############
# (C) 2011,2019 Andreas Kupries

# Facade concatenating the contents of the channels it was constructed
# with. Owns the sub-ordinate channels and closes them on exhaustion and/or
# when closed itself.

# @@ Meta Begin
# Package tcl::chan::cat 1.0.3
# Meta as::author {Andreas Kupries}
# Meta as::copyright 2011
# Meta as::license BSD
# Meta description Facade concatenating the contents of the channels it
# Meta description was constructed with. Owns the sub-ordinate channels
# Meta description and closes them on exhaustion and/or when closed itself.
# Meta platform tcl
................................................................................

    # We are not using the standard event handling class, because here
    # it will not be timer-driven. We propagate anything related to
    # events to catin and catout instead and let them handle things.

    constructor {args} {
	set channels $args
	# Disable translation (and hence encoding) in the wrapped channels.
	# This will happen in our generic layer instead.
	foreach c $channels {

	    fconfigure $c -translation binary
	}
	set delay 10
	set watching 0
	return
    }

................................................................................
    method watch {c requestmask} {
	if {"read" in $requestmask} {
	    # Activate event handling.  Either drive an eof home via
	    # timers, or activate things in the foremost sub-ordinate.

	    set watching 1
	    if {![llength $channels]} {

		set timer [after $delay [namespace code [list my Post $c]]]
	    } else {
		chan event [lindex $channels 0] readable [list chan postevent $c read]

	    }
	} else {
	    # Stop events. Either kill timer, or disable in the
	    # foremost sub-ordinate.

	    set watching 0
	    if {![llength $channels]} {
		catch { after cancel $timer }
	    } else {
		chan event [lindex $channels 0] readable {}
	    }
	}
	return
    }

    method read {c n} {
	if {![llength $channels]} {
	    # This signals EOF higher up.
	    return {}
	}

	set buf {}
	while {([string length $buf] < $n) &&
	       [llength $channels]} {

................................................................................
	    set toread [expr {$n - [string length $buf]}]
	    append buf [::read $in $toread]

	    if {[eof $in]} {
		close $in
		set channels [lrange $channels 1 end]

		# The close of the exhausted subordinate killed any
		# fileevent handling we may have had attached to this
		# channel. Update the settings (i.e. move to the next
		# subordinate, or to timer-based, to drive the eof
		# home).

		if {$watching} {
		    my watch $c read
		}
	    }
	}

	# When `buf` is empty, all channels have been exhausted and
	# closed, therefore returning this empty string will cause an


	# EOF higher up.
	return $buf
    }

    method Post {c} {

	set timer [after $delay [namespace code [list my Post $c]]]
	chan postevent $c read
	return
    }
}

# # ## ### ##### ######## #############
package provide tcl::chan::cat 1.0.3
return

Added modules/virtchannel_base/cat.test.










































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#- - -- --- ----- -------- ------------- ---------------------
# cat.test -*- tcl -*-
# (C) 2019 Andreas Kupries. BSD licensed.
#- - -- --- ----- -------- ------------- ---------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0
testsNeed        TclOO 1

support {
    use virtchannel_core/core.tcl   tcl::chan::core
    use virtchannel_core/events.tcl tcl::chan::events
    useLocal string.tcl tcl::chan::string
}
testing {
    useLocal cat.tcl tcl::chan::cat
}

#- - -- --- ----- -------- ------------- ---------------------
## No wrong#args, allowed to zero and up

#- - -- --- ----- -------- ------------- ---------------------

test tcl-chan-cat-2.0 {tell, nothing} -setup {
    set c [tcl::chan::cat]
} -body {
    tell $c
} -cleanup {
    close $c
    unset c
} -result -1

test tcl-chan-cat-2.1 {ticket 1975182bdd - file events} -setup {
    # setup a cat'enated channel
    set fa [tcl::chan::string "ABCDE..XYZ"]
    set fb [tcl::chan::string "0123456789"]
    set ch [tcl::chan::cat $fa $fb]
} -body {
    set r {}
    chan event $ch readable {
        if { [eof $ch] } {
            set done .
        } else {
            lappend r [read $ch 4]
        }
    }    
    vwait done
    set r
} -cleanup {
    close $ch
    unset ch fa fb r
} -result {ABCD E..X YZ01 2345 6789 {}}

#- - -- --- ----- -------- ------------- ---------------------
# Explicit cleanup of loaded support classes.

rename tcl::chan::events {}
rename tcl::chan::core   {}
testsuiteCleanup
return

# Local Variables:
#  mode: tcl
#  indent-tabs-mode: nil
# End:

Changes to modules/virtchannel_base/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
if {![package vsatisfies [package provide Tcl] 8.5]} {return}

package ifneeded tcl::chan::cat 1.0.2      [list source [file join $dir cat.tcl]]
package ifneeded tcl::chan::facade 1.0.1   [list source [file join $dir facade.tcl]]
package ifneeded tcl::chan::fifo 1         [list source [file join $dir fifo.tcl]]
package ifneeded tcl::chan::fifo2 1        [list source [file join $dir fifo2.tcl]]
package ifneeded tcl::chan::halfpipe 1     [list source [file join $dir halfpipe.tcl]]
package ifneeded tcl::chan::memchan 1.0.4  [list source [file join $dir memchan.tcl]]
package ifneeded tcl::chan::null 1         [list source [file join $dir null.tcl]]
package ifneeded tcl::chan::nullzero 1     [list source [file join $dir nullzero.tcl]]

|







1
2
3
4
5
6
7
8
9
10
if {![package vsatisfies [package provide Tcl] 8.5]} {return}

package ifneeded tcl::chan::cat 1.0.3      [list source [file join $dir cat.tcl]]
package ifneeded tcl::chan::facade 1.0.1   [list source [file join $dir facade.tcl]]
package ifneeded tcl::chan::fifo 1         [list source [file join $dir fifo.tcl]]
package ifneeded tcl::chan::fifo2 1        [list source [file join $dir fifo2.tcl]]
package ifneeded tcl::chan::halfpipe 1     [list source [file join $dir halfpipe.tcl]]
package ifneeded tcl::chan::memchan 1.0.4  [list source [file join $dir memchan.tcl]]
package ifneeded tcl::chan::null 1         [list source [file join $dir null.tcl]]
package ifneeded tcl::chan::nullzero 1     [list source [file join $dir nullzero.tcl]]